mirror of
https://github.com/mappu/miqt.git
synced 2024-12-22 00:48:38 +00:00
genbindings: subclass support for all virtual methods (3/3)
This commit is contained in:
parent
58f212303e
commit
943ccf7b3a
@ -718,9 +718,9 @@ extern "C" {
|
||||
}
|
||||
|
||||
for _, m := range c.VirtualMethods() {
|
||||
ret.WriteString(fmt.Sprintf("void %s_override_virtual_%s(%s* self, intptr_t slot);\n", methodPrefixName, m.SafeMethodName(), methodPrefixName))
|
||||
ret.WriteString(fmt.Sprintf("void %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 ", "")+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*/ +"*")))
|
||||
}
|
||||
|
||||
// delete
|
||||
@ -786,18 +786,27 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
||||
|
||||
ret.WriteString("class " + overriddenClassName + " : public virtual " + cppClassName + " {\n" +
|
||||
"public:\n" +
|
||||
"\tusing " + fullyQualifiedConstructor(cppClassName) + ";\n" + // inherit constructors
|
||||
"\n",
|
||||
)
|
||||
|
||||
for _, ctor := range c.Ctors {
|
||||
ret.WriteString("\t" + overriddenClassName + "(" + emitParametersCpp(ctor) + "): " + cppClassName + "(" + emitParameterNames(ctor) + ") {};\n")
|
||||
}
|
||||
ret.WriteString("\n")
|
||||
|
||||
if !c.CanDelete {
|
||||
ret.WriteString(
|
||||
"private:\n" +
|
||||
"\t~" + overriddenClassName + "();\n" + // = delete;\n" +
|
||||
"\tvirtual ~" + overriddenClassName + "();\n" + // = delete;\n" +
|
||||
"\n" +
|
||||
"public:\n" +
|
||||
"\n",
|
||||
)
|
||||
} else {
|
||||
ret.WriteString(
|
||||
"\tvirtual ~" + overriddenClassName + "() = default;\n" +
|
||||
"\n",
|
||||
)
|
||||
}
|
||||
|
||||
for _, m := range virtualMethods {
|
||||
@ -834,7 +843,7 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
||||
|
||||
ret.WriteString(
|
||||
"\t// Subclass to allow providing a Go implementation\n" +
|
||||
"\t" + m.ReturnType.RenderTypeQtCpp() + " " + m.CppCallTarget() + "(" + emitParametersCpp(m) + ") " + ifv(m.IsConst, "const ", "") + "override {\n" +
|
||||
"\tvirtual " + m.ReturnType.RenderTypeQtCpp() + " " + m.CppCallTarget() + "(" + emitParametersCpp(m) + ") " + ifv(m.IsConst, "const ", "") + "override {\n" +
|
||||
"\t\tif (handle__" + m.SafeMethodName() + " == 0) {\n",
|
||||
)
|
||||
if m.IsPureVirtual {
|
||||
@ -845,6 +854,10 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
||||
}
|
||||
} else {
|
||||
ret.WriteString("\t\t\t" + maybeReturn + methodPrefixName + "::" + m.CppCallTarget() + "(" + emitParameterNames(m) + ");\n")
|
||||
|
||||
if m.ReturnType.Void() {
|
||||
ret.WriteString("\t\t\treturn;\n")
|
||||
}
|
||||
}
|
||||
ret.WriteString(
|
||||
"\t\t}\n" +
|
||||
@ -874,12 +887,6 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
||||
}
|
||||
vbpreamble, vbforwarding := emitParametersCABI2CppForwarding(m.Parameters, "\t\t")
|
||||
|
||||
// To call the super/parent's version of this method, normally
|
||||
// we use the scope operator (Base::Foo()), but that only works
|
||||
// inside the actual overridden method itself
|
||||
// Use a reinterpret_cast<> instead
|
||||
|
||||
// vbCallTarget := "reinterpret_cast<" + ifv(m.IsConst, "const ", "") + c.ClassName + "*>(this)->" + m.CppCallTarget() + "(" + vbforwarding + ")"
|
||||
vbCallTarget := methodPrefixName + "::" + m.CppCallTarget() + "(" + vbforwarding + ")"
|
||||
|
||||
ret.WriteString(
|
||||
@ -904,18 +911,6 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
||||
|
||||
for i, ctor := range c.Ctors {
|
||||
|
||||
if len(virtualMethods) > 0 &&
|
||||
len(ctor.Parameters) == 1 &&
|
||||
ctor.Parameters[0].ParameterType == c.ClassName &&
|
||||
(ctor.Parameters[0].Pointer || ctor.Parameters[0].ByRef) {
|
||||
// This is a copy-constructor for the base class
|
||||
// We can't just call it on the derived class, that doesn't work:
|
||||
// ""an inherited constructor is not a candidate for initialization from an expression of the same or derived type""
|
||||
// @ref https://stackoverflow.com/q/57926023
|
||||
// FIXME need to block this in the header and in Go as well
|
||||
continue
|
||||
}
|
||||
|
||||
preamble, forwarding := emitParametersCABI2CppForwarding(ctor.Parameters, "\t")
|
||||
|
||||
if ctor.LinuxOnly {
|
||||
@ -1063,8 +1058,8 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
||||
// (Never use a const self*)
|
||||
|
||||
ret.WriteString(
|
||||
`void ` + methodPrefixName + `_override_virtual_` + m.SafeMethodName() + `(` + methodPrefixName + `* self, intptr_t slot) {` + "\n" +
|
||||
"\tdynamic_cast<" + cppClassName + "*>(self)->handle__" + m.SafeMethodName() + " = slot;\n" +
|
||||
`void ` + methodPrefixName + `_override_virtual_` + m.SafeMethodName() + `(void* self, intptr_t slot) {` + "\n" +
|
||||
"\t( (" + cppClassName + "*)(self) )->handle__" + m.SafeMethodName() + " = slot;\n" +
|
||||
"}\n" +
|
||||
"\n",
|
||||
)
|
||||
@ -1088,10 +1083,10 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
||||
// callTarget is an rvalue representing the full C++ function call.
|
||||
// These are never static
|
||||
|
||||
callTarget := "dynamic_cast<" + ifv(m.IsConst, "const ", "") + cppClassName + "*>(self)->virtualbase_" + m.SafeMethodName() + "(" + strings.Join(parameterNames, `, `) + ")"
|
||||
callTarget := "( (" + ifv(m.IsConst, "const ", "") + cppClassName + "*)(self) )->virtualbase_" + m.SafeMethodName() + "(" + strings.Join(parameterNames, `, `) + ")"
|
||||
|
||||
ret.WriteString(
|
||||
m.ReturnType.RenderTypeCabi() + " " + methodPrefixName + "_virtualbase_" + m.SafeMethodName() + "(" + emitParametersCabi(m, ifv(m.IsConst, "const ", "")+methodPrefixName+"*") + ") {\n" +
|
||||
m.ReturnType.RenderTypeCabi() + " " + methodPrefixName + "_virtualbase_" + m.SafeMethodName() + "(" + emitParametersCabi(m, ifv(m.IsConst, "const ", "")+"void*") + ") {\n" +
|
||||
"\t" + ifv(m.ReturnType.Void(), "", "return ") + callTarget + ";\n" +
|
||||
"}\n" +
|
||||
"\n",
|
||||
|
@ -806,6 +806,11 @@ import "C"
|
||||
}
|
||||
|
||||
for _, m := range c.Methods {
|
||||
|
||||
if m.IsProtected {
|
||||
continue // Don't add a direct call for it
|
||||
}
|
||||
|
||||
preamble, forwarding := gfs.emitParametersGo2CABIForwarding(m)
|
||||
|
||||
returnTypeDecl := m.ReturnType.RenderTypeGo(&gfs)
|
||||
@ -910,7 +915,7 @@ import "C"
|
||||
}
|
||||
|
||||
ret.WriteString(`func (this *` + goClassName + `) On` + m.SafeMethodName() + `(slot ` + goCbType + `) {
|
||||
C.` + goClassName + `_override_virtual_` + m.SafeMethodName() + `(this.h, C.intptr_t(cgo.NewHandle(slot)) )
|
||||
C.` + goClassName + `_override_virtual_` + m.SafeMethodName() + `(unsafe.Pointer(this.h), C.intptr_t(cgo.NewHandle(slot)) )
|
||||
}
|
||||
|
||||
//export miqt_exec_callback_` + goClassName + `_` + m.SafeMethodName() + `
|
||||
|
@ -394,6 +394,28 @@ func (c *CppClass) VirtualMethods() []CppMethod {
|
||||
var retNames = make(map[string]struct{}, 0) // if name is present, a child class found it first
|
||||
var block = slice_to_set(c.PrivateMethods)
|
||||
|
||||
if len(c.Ctors) == 0 {
|
||||
// This class can't be constructed
|
||||
// Therefore there's no way to get a derived version of it for subclassing
|
||||
// (Unless we add custom constructors, but that seems like there would be
|
||||
// no in-Qt use for such a thing)
|
||||
// Pretend that this class is non-virtual
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME Allowing the subclassing of QAccessibleWidget compiles fine,
|
||||
// but, always gives a linker error:
|
||||
//
|
||||
// /usr/lib/go-1.19/pkg/tool/linux_amd64/link: running g++ failed: exit status 1
|
||||
// /usr/bin/ld: /tmp/go-link-1745036494/000362.o: in function `MiqtVirtualQAccessibleWidget::MiqtVirtualQAccessibleWidget(QWidget*)':
|
||||
// undefined reference to `vtable for MiqtVirtualQAccessibleWidget'
|
||||
//
|
||||
// An undefined vtable usually indicates that the virtual class is missing
|
||||
// definitions for some virtual methods, but AFAICT we have complete coverage.
|
||||
if c.ClassName == "QAccessibleWidget" {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, m := range c.Methods {
|
||||
if !m.IsVirtual {
|
||||
continue
|
||||
|
Loading…
Reference in New Issue
Block a user