genbindings: use dynamic_cast's return value to verify override is safe

This commit is contained in:
mappu 2025-01-18 17:57:16 +13:00
parent 693760653d
commit 3697849067
2 changed files with 11 additions and 5 deletions

View File

@ -749,7 +749,7 @@ extern "C" {
} }
for _, m := range c.VirtualMethods() { for _, m := range c.VirtualMethods() {
ret.WriteString(fmt.Sprintf("void %s_override_virtual_%s(%s* self, intptr_t slot);\n", methodPrefixName, m.SafeMethodName(), "void" /*methodPrefixName*/)) ret.WriteString(fmt.Sprintf("bool %s_override_virtual_%s(%s* self, intptr_t slot);\n", methodPrefixName, m.SafeMethodName(), "void" /*methodPrefixName*/))
ret.WriteString(fmt.Sprintf("%s %s_virtualbase_%s(%s);\n", m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+"void" /*methodPrefixName*/ +"*"))) ret.WriteString(fmt.Sprintf("%s %s_virtualbase_%s(%s);\n", m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+"void" /*methodPrefixName*/ +"*")))
} }
@ -1178,8 +1178,14 @@ extern "C" {
// upclass it // upclass it
ret.WriteString( ret.WriteString(
`void ` + methodPrefixName + `_override_virtual_` + m.SafeMethodName() + `(void* self, intptr_t slot) {` + "\n" + `bool ` + methodPrefixName + `_override_virtual_` + m.SafeMethodName() + `(void* self, intptr_t slot) {` + "\n" +
"\tdynamic_cast<" + cppClassName + "*>( (" + cabiClassName(c.ClassName) + "*)(self) )->handle__" + m.SafeMethodName() + " = slot;\n" + "\t" + cppClassName + "* self_cast = dynamic_cast<" + cppClassName + "*>( (" + cabiClassName(c.ClassName) + "*)(self) );\n" +
"\tif (self_cast == nullptr) {\n" +
"\t\treturn false;\n" +
"\t}\n" +
"\t\n" +
"\tself_cast->handle__" + m.SafeMethodName() + " = slot;\n" +
"\treturn true;\n" +
"}\n" + "}\n" +
"\n", "\n",
) )

View File

@ -1035,10 +1035,10 @@ import "C"
goCbType += `) ` + m.ReturnType.renderReturnTypeGo(&gfs) goCbType += `) ` + m.ReturnType.renderReturnTypeGo(&gfs)
callbackName := cabiCallbackName(c, m) callbackName := cabiCallbackName(c, m)
ret.WriteString(`func (this *` + goClassName + `) On` + m.SafeMethodName() + `(slot ` + goCbType + `) { ret.WriteString(`func (this *` + goClassName + `) On` + m.SafeMethodName() + `(slot ` + goCbType + `) {
if ! this.isSubclass { ok := C.` + goClassName + `_override_virtual_` + m.SafeMethodName() + `(unsafe.Pointer(this.h), C.intptr_t(cgo.NewHandle(slot)) )
if !ok {
panic("miqt: can only override virtual methods for directly constructed types") panic("miqt: can only override virtual methods for directly constructed types")
} }
C.` + goClassName + `_override_virtual_` + m.SafeMethodName() + `(unsafe.Pointer(this.h), C.intptr_t(cgo.NewHandle(slot)) )
} }
//export ` + callbackName + ` //export ` + callbackName + `