mirror of
https://github.com/mappu/miqt.git
synced 2025-01-03 06:08:38 +00:00
genbindings: subclass support for all virtual methods (1/3)
This commit is contained in:
parent
9b37750d64
commit
aa2fdf98ca
@ -460,6 +460,14 @@ nextMethod:
|
|||||||
}
|
}
|
||||||
|
|
||||||
mm.IsSignal = isSignal && !mm.IsStatic && AllowSignal(mm)
|
mm.IsSignal = isSignal && !mm.IsStatic && AllowSignal(mm)
|
||||||
|
mm.IsProtected = (visibility == VsProtected)
|
||||||
|
|
||||||
|
if mm.IsProtected && !mm.IsVirtual {
|
||||||
|
// Protected method, so we can't call it
|
||||||
|
// Non-virtual, so we can't override it
|
||||||
|
// There is nothing we can do with this function
|
||||||
|
continue nextMethod
|
||||||
|
}
|
||||||
|
|
||||||
// Once all processing is complete, pass to exceptions for final decision
|
// Once all processing is complete, pass to exceptions for final decision
|
||||||
|
|
||||||
|
@ -186,6 +186,10 @@ func AllowSignal(mm CppMethod) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AllowVirtual(mm CppMethod) bool {
|
||||||
|
return true // AllowSignal(mm)
|
||||||
|
}
|
||||||
|
|
||||||
func AllowMethod(className string, mm CppMethod) error {
|
func AllowMethod(className string, mm CppMethod) error {
|
||||||
|
|
||||||
for _, p := range mm.Parameters {
|
for _, p := range mm.Parameters {
|
||||||
|
@ -674,23 +674,27 @@ extern "C" {
|
|||||||
|
|
||||||
for _, c := range src.Classes {
|
for _, c := range src.Classes {
|
||||||
|
|
||||||
cClassName := cabiClassName(c.ClassName)
|
methodPrefixName := cabiClassName(c.ClassName)
|
||||||
|
|
||||||
for i, ctor := range c.Ctors {
|
for i, ctor := range c.Ctors {
|
||||||
ret.WriteString(fmt.Sprintf("%s %s_new%s(%s);\n", cClassName+"*", cClassName, maybeSuffix(i), emitParametersCabi(ctor, "")))
|
ret.WriteString(fmt.Sprintf("%s %s_new%s(%s);\n", methodPrefixName+"*", methodPrefixName, maybeSuffix(i), emitParametersCabi(ctor, "")))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range c.Methods {
|
for _, m := range c.Methods {
|
||||||
ret.WriteString(fmt.Sprintf("%s %s_%s(%s);\n", m.ReturnType.RenderTypeCabi(), cClassName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+cClassName+"*")))
|
ret.WriteString(fmt.Sprintf("%s %s_%s(%s);\n", m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+methodPrefixName+"*")))
|
||||||
|
|
||||||
if m.IsSignal {
|
if m.IsSignal {
|
||||||
ret.WriteString(fmt.Sprintf("%s %s_connect_%s(%s* self, intptr_t slot);\n", m.ReturnType.RenderTypeCabi(), cClassName, m.SafeMethodName(), cClassName))
|
ret.WriteString(fmt.Sprintf("%s %s_connect_%s(%s* self, intptr_t slot);\n", m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), methodPrefixName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, m := range c.VirtualMethods() {
|
||||||
|
ret.WriteString(fmt.Sprintf("void %s_override_virtual_%s(%s* self, intptr_t slot);\n", methodPrefixName, m.SafeMethodName(), methodPrefixName))
|
||||||
|
}
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
if c.CanDelete {
|
if c.CanDelete {
|
||||||
ret.WriteString(fmt.Sprintf("void %s_Delete(%s* self);\n", cClassName, cClassName))
|
ret.WriteString(fmt.Sprintf("void %s_Delete(%s* self);\n", methodPrefixName, methodPrefixName))
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.WriteString("\n")
|
ret.WriteString("\n")
|
||||||
@ -736,7 +740,49 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
|
|
||||||
for _, c := range src.Classes {
|
for _, c := range src.Classes {
|
||||||
|
|
||||||
cClassName := cabiClassName(c.ClassName)
|
methodPrefixName := cabiClassName(c.ClassName)
|
||||||
|
cppClassName := c.ClassName
|
||||||
|
virtualMethods := c.VirtualMethods()
|
||||||
|
|
||||||
|
if len(virtualMethods) > 0 {
|
||||||
|
ret.WriteString("class MiqtVirtual" + cppClassName + " : public virtual " + cppClassName + " {\n" +
|
||||||
|
"public:\n" +
|
||||||
|
"\tusing " + cppClassName + "::" + cppClassName + ";\n" + // inherit constructors
|
||||||
|
"\n",
|
||||||
|
)
|
||||||
|
for _, m := range virtualMethods {
|
||||||
|
|
||||||
|
maybeReturn := ifv(m.ReturnType.RenderTypeQtCpp() == "void", "", "return ")
|
||||||
|
|
||||||
|
ret.WriteString(
|
||||||
|
"\tintptr_t handle__" + m.SafeMethodName() + " = 0;\n" +
|
||||||
|
|
||||||
|
"\n" +
|
||||||
|
|
||||||
|
"\t" + m.ReturnType.RenderTypeQtCpp() + " " + m.MethodName + "(...) override {\n" +
|
||||||
|
"\t\tif (handle__" + m.SafeMethodName() + " == 0) {\n" +
|
||||||
|
"\t\t\t" + maybeReturn + methodPrefixName + "::" + m.MethodName + "(...);\n" +
|
||||||
|
"\t\t} else {\n" +
|
||||||
|
"\t\t\t" + maybeReturn + "miqt_exec_callback_" + methodPrefixName + "_" + m.SafeMethodName() + "(...);\n" +
|
||||||
|
"\t\t}\n" +
|
||||||
|
"\t}\n" +
|
||||||
|
|
||||||
|
"\n" +
|
||||||
|
|
||||||
|
"\t" + m.ReturnType.RenderTypeQtCpp() + " virtualbase_" + m.SafeMethodName() + "(...) {\n" +
|
||||||
|
"\t\t" + maybeReturn + methodPrefixName + "::" + m.MethodName + "(...);\n" +
|
||||||
|
"\t}\n" +
|
||||||
|
|
||||||
|
"\n",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.WriteString(
|
||||||
|
"};\n" +
|
||||||
|
"\n")
|
||||||
|
|
||||||
|
cppClassName = "MiqtVirtual" + cppClassName
|
||||||
|
}
|
||||||
|
|
||||||
for i, ctor := range c.Ctors {
|
for i, ctor := range c.Ctors {
|
||||||
|
|
||||||
@ -754,9 +800,9 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
"#endif\n"+
|
"#endif\n"+
|
||||||
"}\n"+
|
"}\n"+
|
||||||
"\n",
|
"\n",
|
||||||
cClassName, cClassName, maybeSuffix(i), emitParametersCabi(ctor, ""),
|
methodPrefixName, methodPrefixName, maybeSuffix(i), emitParametersCabi(ctor, ""),
|
||||||
preamble,
|
preamble,
|
||||||
c.ClassName, forwarding,
|
cppClassName, forwarding,
|
||||||
))
|
))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -766,9 +812,9 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
"\treturn new %s(%s);\n"+
|
"\treturn new %s(%s);\n"+
|
||||||
"}\n"+
|
"}\n"+
|
||||||
"\n",
|
"\n",
|
||||||
cClassName, cClassName, maybeSuffix(i), emitParametersCabi(ctor, ""),
|
methodPrefixName, methodPrefixName, maybeSuffix(i), emitParametersCabi(ctor, ""),
|
||||||
preamble,
|
preamble,
|
||||||
c.ClassName, forwarding,
|
cppClassName, forwarding,
|
||||||
))
|
))
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -800,7 +846,7 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
"#endif\n"+
|
"#endif\n"+
|
||||||
"}\n"+
|
"}\n"+
|
||||||
"\n",
|
"\n",
|
||||||
m.ReturnType.RenderTypeCabi(), cClassName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+cClassName+"*"),
|
m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+methodPrefixName+"*"),
|
||||||
preamble,
|
preamble,
|
||||||
emitAssignCppToCabi("\treturn ", m.ReturnType, callTarget),
|
emitAssignCppToCabi("\treturn ", m.ReturnType, callTarget),
|
||||||
m.ReturnType.RenderTypeCabi(),
|
m.ReturnType.RenderTypeCabi(),
|
||||||
@ -808,10 +854,10 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
|
|
||||||
} else if m.BecomesNonConstInVersion != nil {
|
} else if m.BecomesNonConstInVersion != nil {
|
||||||
|
|
||||||
nonConstCallTarget := "const_cast<" + cClassName + "*>(self)->" + m.CppCallTarget() + "(" + forwarding + ")"
|
nonConstCallTarget := "const_cast<" + methodPrefixName + "*>(self)->" + m.CppCallTarget() + "(" + forwarding + ")"
|
||||||
|
|
||||||
ret.WriteString("" +
|
ret.WriteString("" +
|
||||||
m.ReturnType.RenderTypeCabi() + " " + cClassName + "_" + m.SafeMethodName() + "(" + emitParametersCabi(m, ifv(m.IsConst, "const ", "")+cClassName+"*") + ") {\n" +
|
m.ReturnType.RenderTypeCabi() + " " + methodPrefixName + "_" + m.SafeMethodName() + "(" + emitParametersCabi(m, ifv(m.IsConst, "const ", "")+methodPrefixName+"*") + ") {\n" +
|
||||||
preamble + "\n" +
|
preamble + "\n" +
|
||||||
"// This method was changed from const to non-const in Qt " + *m.BecomesNonConstInVersion + "\n" +
|
"// This method was changed from const to non-const in Qt " + *m.BecomesNonConstInVersion + "\n" +
|
||||||
"#if QT_VERSION < QT_VERSION_CHECK(" + strings.Replace(*m.BecomesNonConstInVersion, `.`, `,`, -1) + ",0)\n" +
|
"#if QT_VERSION < QT_VERSION_CHECK(" + strings.Replace(*m.BecomesNonConstInVersion, `.`, `,`, -1) + ",0)\n" +
|
||||||
@ -831,7 +877,7 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
"%s"+
|
"%s"+
|
||||||
"}\n"+
|
"}\n"+
|
||||||
"\n",
|
"\n",
|
||||||
m.ReturnType.RenderTypeCabi(), cClassName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+cClassName+"*"),
|
m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+methodPrefixName+"*"),
|
||||||
preamble,
|
preamble,
|
||||||
emitAssignCppToCabi("\treturn ", m.ReturnType, callTarget),
|
emitAssignCppToCabi("\treturn ", m.ReturnType, callTarget),
|
||||||
))
|
))
|
||||||
@ -860,8 +906,8 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
signalCode += "\t\t" + bindingFunc + "(" + strings.Join(paramArgs, `, `) + ");\n"
|
signalCode += "\t\t" + bindingFunc + "(" + strings.Join(paramArgs, `, `) + ");\n"
|
||||||
|
|
||||||
ret.WriteString(
|
ret.WriteString(
|
||||||
`void ` + cClassName + `_connect_` + m.SafeMethodName() + `(` + cClassName + `* self, intptr_t slot) {` + "\n" +
|
`void ` + methodPrefixName + `_connect_` + m.SafeMethodName() + `(` + methodPrefixName + `* self, intptr_t slot) {` + "\n" +
|
||||||
"\t" + c.ClassName + `::connect(self, ` + exactSignal + `, self, [=](` + emitParametersCpp(m) + `) {` + "\n" +
|
"\t" + cppClassName + `::connect(self, ` + exactSignal + `, self, [=](` + emitParametersCpp(m) + `) {` + "\n" +
|
||||||
signalCode +
|
signalCode +
|
||||||
"\t});\n" +
|
"\t});\n" +
|
||||||
"}\n" +
|
"}\n" +
|
||||||
@ -871,6 +917,17 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Virtual override helpers
|
||||||
|
for _, m := range virtualMethods {
|
||||||
|
ret.WriteString(
|
||||||
|
`void ` + methodPrefixName + `_override_virtual_` + m.SafeMethodName() + `(` + methodPrefixName + `* self, intptr_t slot) {` + "\n" +
|
||||||
|
"\tstatic_cast<" + cppClassName + ">(self)->handle__" + m.SafeMethodName() + " = slot;\n" +
|
||||||
|
"}\n" +
|
||||||
|
"\n",
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
if c.CanDelete {
|
if c.CanDelete {
|
||||||
ret.WriteString(fmt.Sprintf(
|
ret.WriteString(fmt.Sprintf(
|
||||||
@ -878,7 +935,7 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
"\tdelete self;\n"+
|
"\tdelete self;\n"+
|
||||||
"}\n"+
|
"}\n"+
|
||||||
"\n",
|
"\n",
|
||||||
cClassName, cClassName,
|
methodPrefixName, methodPrefixName,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,8 @@ type CppMethod struct {
|
|||||||
IsStatic bool
|
IsStatic bool
|
||||||
IsSignal bool
|
IsSignal bool
|
||||||
IsConst bool
|
IsConst bool
|
||||||
|
IsVirtual bool
|
||||||
|
IsProtected bool // If true, we can't call this method but we may still be able to overload it
|
||||||
HiddenParams []CppParameter // Populated if there is an overload with more parameters
|
HiddenParams []CppParameter // Populated if there is an overload with more parameters
|
||||||
|
|
||||||
// Special quirks
|
// Special quirks
|
||||||
@ -382,6 +384,56 @@ type CppClass struct {
|
|||||||
ChildEnums []CppEnum
|
ChildEnums []CppEnum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Virtual checks if the class has any virtual methods. This requires global
|
||||||
|
// state knowledge as virtual methods might have been inherited.
|
||||||
|
// C++ constructors cannot be virtual.
|
||||||
|
func (c *CppClass) VirtualMethods() []CppMethod {
|
||||||
|
var ret []CppMethod
|
||||||
|
var retNames = make(map[string]struct{}, 0) // if name is present, a child class found it first
|
||||||
|
|
||||||
|
for _, m := range c.Methods {
|
||||||
|
if !m.IsVirtual {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if m.IsSignal {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !AllowVirtual(m) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, m)
|
||||||
|
retNames[m.MethodName] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, inh := range c.Inherits {
|
||||||
|
cinfo, ok := KnownClassnames[inh]
|
||||||
|
if !ok {
|
||||||
|
panic("Class " + c.ClassName + " inherits from unknown class " + inh)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range cinfo.Class.Methods {
|
||||||
|
if !m.IsVirtual {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if m.IsSignal {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !AllowVirtual(m) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := retNames[m.MethodName]; ok {
|
||||||
|
continue // Already found in a child class
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, m)
|
||||||
|
retNames[m.MethodName] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
type CppTypedef struct {
|
type CppTypedef struct {
|
||||||
Alias string
|
Alias string
|
||||||
UnderlyingType CppParameter
|
UnderlyingType CppParameter
|
||||||
|
Loading…
Reference in New Issue
Block a user