genbindings: use knownClassNames tracker to distinguish A::B names

This commit is contained in:
mappu 2024-08-26 22:48:37 +12:00
parent 02370ce0ea
commit 85cf3b84d8
4 changed files with 63 additions and 22 deletions

View File

@ -46,7 +46,13 @@ func (p CppParameter) RenderTypeCabi() string {
}
if strings.Contains(p.ParameterType, `::`) {
ret = "int"
if _, ok := KnownClassnames[p.ParameterType]; ok {
// Inner class
ret = cabiClassName(p.ParameterType)
} else {
// Enum
ret = "uintptr_t"
}
}
if p.Pointer || p.ByRef {
@ -64,11 +70,11 @@ func emitReturnTypeCabi(p CppParameter) string {
return "void" // Will be handled separately
} else if (p.Pointer || p.ByRef) && p.QtClassType() {
return p.ParameterType + "*" // CABI type
return cabiClassName(p.ParameterType) + "*" // CABI type
} else if p.QtClassType() && !p.Pointer {
// Even if C++ returns by value, CABI is returning a heap copy (new'd, not malloc'd)
return p.ParameterType + "*" // CABI type
return cabiClassName(p.ParameterType) + "*" // CABI type
// return "void" // Handled separately with an _out pointer
} else {
@ -77,10 +83,8 @@ func emitReturnTypeCabi(p CppParameter) string {
}
func (p CppParameter) RenderTypeQtCpp() string {
cppType := p.ParameterType
if len(p.TypeAlias) > 0 {
cppType = p.TypeAlias // replace
}
cppType := p.UnderlyingType()
if p.Const {
cppType = "const " + cppType
}
@ -147,13 +151,13 @@ func emitParametersCabi(m CppMethod, selfType string) string {
} else if (p.ByRef || p.Pointer) && p.QtClassType() {
// Pointer to Qt type
// Replace with taking our PQ typedef by value
tmp = append(tmp, p.ParameterType+"* "+p.ParameterName)
tmp = append(tmp, cabiClassName(p.ParameterType)+"* "+p.ParameterName)
} else if p.QtClassType() {
// Qt type passed by value
// The CABI will unconditionally take these by pointer and dereference them
// when passing to C++
tmp = append(tmp, p.ParameterType+"* "+p.ParameterName)
tmp = append(tmp, cabiClassName(p.ParameterType)+"* "+p.ParameterName)
} else {
// RenderTypeCabi renders both pointer+reference as pointers
@ -235,13 +239,9 @@ func emitParametersCABI2CppForwarding(params []CppParameter) (preamble string, f
// Use the raw ParameterType to select an explicit integer overload
// Don't use RenderTypeCabi() since it canonicalizes some int types for CABI
castSrc := p.ParameterName
castType := p.ParameterType
if p.Pointer {
castType += "*"
}
castType := p.RenderTypeQtCpp()
if p.ByRef { // e.g. QDataStream::operator>>() overloads
castSrc = "*" + castSrc
castType += "&" // believe it or not, this is legal
}
if p.ParameterType == "qint64" || p.ParameterType == "quint64" || p.ParameterType == "qlonglong" || p.ParameterType == "qulonglong" {

View File

@ -88,7 +88,13 @@ func (p CppParameter) RenderTypeGo() string {
default:
if strings.Contains(p.ParameterType, `::`) {
ret += "int"
if _, ok := KnownClassnames[p.ParameterType]; ok {
// Inner class
ret += cabiClassName(p.ParameterType)
} else {
// Enum
ret += "uintptr"
}
} else {
// Do not transform this type
ret += p.ParameterType
@ -314,7 +320,7 @@ import "C"
localInit := "h: h"
for _, base := range c.Inherits {
gfs.imports["unsafe"] = struct{}{}
localInit += ", " + base + ": new" + base + "_U(unsafe.Pointer(h))"
localInit += ", " + base + ": new" + cabiClassName(base) + "_U(unsafe.Pointer(h))"
}
ret.WriteString(`
@ -419,9 +425,9 @@ import "C"
if t.QtClassType() {
if !t.Pointer {
// new, but then dereference it
afterword += "ret[i] = *new" + t.ParameterType + "(_outCast[i])\n"
afterword += "ret[i] = *new" + cabiClassName(t.ParameterType) + "(_outCast[i])\n"
} else {
afterword += "ret[i] = new" + t.ParameterType + "(_outCast[i])\n"
afterword += "ret[i] = new" + cabiClassName(t.ParameterType) + "(_outCast[i])\n"
}
} else { // plain int type
afterword += "ret[i] = (" + t.RenderTypeGo() + ")(_outCast[i])\n"
@ -437,7 +443,7 @@ import "C"
if m.ReturnType.Pointer || m.ReturnType.ByRef {
gfs.imports["unsafe"] = struct{}{}
afterword = "return new" + m.ReturnType.ParameterType + "_U(unsafe.Pointer(ret))"
afterword = "return new" + cabiClassName(m.ReturnType.ParameterType) + "_U(unsafe.Pointer(ret))"
} else {
// This is return by value, but CABI has new'd it into a
@ -449,8 +455,8 @@ import "C"
gfs.imports["runtime"] = struct{}{}
afterword = "// Qt uses pass-by-value semantics for this type. Mimic with finalizer\n"
afterword += "ret1 := new" + m.ReturnType.ParameterType + "(ret)\n"
afterword += "runtime.SetFinalizer(ret1, func(ret2 *" + m.ReturnType.ParameterType + ") {\n"
afterword += "ret1 := new" + cabiClassName(m.ReturnType.ParameterType) + "(ret)\n"
afterword += "runtime.SetFinalizer(ret1, func(ret2 *" + cabiClassName(m.ReturnType.ParameterType) + ") {\n"
afterword += "ret2.Delete()\n"
afterword += "runtime.KeepAlive(ret2.h)\n"
afterword += "})\n"

View File

@ -5,6 +5,14 @@ import (
"strings"
)
var (
KnownClassnames map[string]struct{} // Entries of the form QFoo::Bar if it is an inner class
)
func init() {
KnownClassnames = make(map[string]struct{})
}
type CppParameter struct {
ParameterName string
ParameterType string
@ -15,8 +23,30 @@ type CppParameter struct {
Optional bool
}
func (p *CppParameter) UnderlyingType() string {
if p.TypeAlias != "" {
return p.TypeAlias
}
return p.ParameterType
}
func (p CppParameter) QtClassType() bool {
return (p.ParameterType[0] == 'Q') && p.ParameterType != "QRgb" && !strings.Contains(p.ParameterType, `::`)
if p.ParameterType[0] != 'Q' {
return false
}
if strings.Contains(p.ParameterType, `::`) {
// Maybe if it's an inner class
if _, ok := KnownClassnames[p.ParameterType]; ok {
return true
}
// Int type
return false
}
// Passed all conditions
return true
}
func (p CppParameter) QListOf() (CppParameter, bool) {

View File

@ -136,6 +136,11 @@ func main() {
astTransformOptional(parsed)
astTransformOverloads(parsed)
// Update global state tracker (AFTER astTransformChildClasses)
// Currently, this is only used for inner classes
for _, c := range parsed.Classes {
KnownClassnames[c.ClassName] = struct{}{}
}
processHeaders = append(processHeaders, parsed)
}