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, `::`) { 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 { if p.Pointer || p.ByRef {
@ -64,11 +70,11 @@ func emitReturnTypeCabi(p CppParameter) string {
return "void" // Will be handled separately return "void" // Will be handled separately
} else if (p.Pointer || p.ByRef) && p.QtClassType() { } 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 { } else if p.QtClassType() && !p.Pointer {
// Even if C++ returns by value, CABI is returning a heap copy (new'd, not malloc'd) // 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 // return "void" // Handled separately with an _out pointer
} else { } else {
@ -77,10 +83,8 @@ func emitReturnTypeCabi(p CppParameter) string {
} }
func (p CppParameter) RenderTypeQtCpp() string { func (p CppParameter) RenderTypeQtCpp() string {
cppType := p.ParameterType cppType := p.UnderlyingType()
if len(p.TypeAlias) > 0 {
cppType = p.TypeAlias // replace
}
if p.Const { if p.Const {
cppType = "const " + cppType cppType = "const " + cppType
} }
@ -147,13 +151,13 @@ func emitParametersCabi(m CppMethod, selfType string) string {
} else if (p.ByRef || p.Pointer) && p.QtClassType() { } else if (p.ByRef || p.Pointer) && p.QtClassType() {
// Pointer to Qt type // Pointer to Qt type
// Replace with taking our PQ typedef by value // 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() { } else if p.QtClassType() {
// Qt type passed by value // Qt type passed by value
// The CABI will unconditionally take these by pointer and dereference them // The CABI will unconditionally take these by pointer and dereference them
// when passing to C++ // when passing to C++
tmp = append(tmp, p.ParameterType+"* "+p.ParameterName) tmp = append(tmp, cabiClassName(p.ParameterType)+"* "+p.ParameterName)
} else { } else {
// RenderTypeCabi renders both pointer+reference as pointers // 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 // Use the raw ParameterType to select an explicit integer overload
// Don't use RenderTypeCabi() since it canonicalizes some int types for CABI // Don't use RenderTypeCabi() since it canonicalizes some int types for CABI
castSrc := p.ParameterName castSrc := p.ParameterName
castType := p.ParameterType castType := p.RenderTypeQtCpp()
if p.Pointer {
castType += "*"
}
if p.ByRef { // e.g. QDataStream::operator>>() overloads if p.ByRef { // e.g. QDataStream::operator>>() overloads
castSrc = "*" + castSrc castSrc = "*" + castSrc
castType += "&" // believe it or not, this is legal
} }
if p.ParameterType == "qint64" || p.ParameterType == "quint64" || p.ParameterType == "qlonglong" || p.ParameterType == "qulonglong" { 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: default:
if strings.Contains(p.ParameterType, `::`) { if strings.Contains(p.ParameterType, `::`) {
ret += "int" if _, ok := KnownClassnames[p.ParameterType]; ok {
// Inner class
ret += cabiClassName(p.ParameterType)
} else {
// Enum
ret += "uintptr"
}
} else { } else {
// Do not transform this type // Do not transform this type
ret += p.ParameterType ret += p.ParameterType
@ -314,7 +320,7 @@ import "C"
localInit := "h: h" localInit := "h: h"
for _, base := range c.Inherits { for _, base := range c.Inherits {
gfs.imports["unsafe"] = struct{}{} gfs.imports["unsafe"] = struct{}{}
localInit += ", " + base + ": new" + base + "_U(unsafe.Pointer(h))" localInit += ", " + base + ": new" + cabiClassName(base) + "_U(unsafe.Pointer(h))"
} }
ret.WriteString(` ret.WriteString(`
@ -419,9 +425,9 @@ import "C"
if t.QtClassType() { if t.QtClassType() {
if !t.Pointer { if !t.Pointer {
// new, but then dereference it // 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 { } else {
afterword += "ret[i] = new" + t.ParameterType + "(_outCast[i])\n" afterword += "ret[i] = new" + cabiClassName(t.ParameterType) + "(_outCast[i])\n"
} }
} else { // plain int type } else { // plain int type
afterword += "ret[i] = (" + t.RenderTypeGo() + ")(_outCast[i])\n" afterword += "ret[i] = (" + t.RenderTypeGo() + ")(_outCast[i])\n"
@ -437,7 +443,7 @@ import "C"
if m.ReturnType.Pointer || m.ReturnType.ByRef { if m.ReturnType.Pointer || m.ReturnType.ByRef {
gfs.imports["unsafe"] = struct{}{} 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 { } else {
// This is return by value, but CABI has new'd it into a // This is return by value, but CABI has new'd it into a
@ -449,8 +455,8 @@ import "C"
gfs.imports["runtime"] = struct{}{} gfs.imports["runtime"] = struct{}{}
afterword = "// Qt uses pass-by-value semantics for this type. Mimic with finalizer\n" afterword = "// Qt uses pass-by-value semantics for this type. Mimic with finalizer\n"
afterword += "ret1 := new" + m.ReturnType.ParameterType + "(ret)\n" afterword += "ret1 := new" + cabiClassName(m.ReturnType.ParameterType) + "(ret)\n"
afterword += "runtime.SetFinalizer(ret1, func(ret2 *" + m.ReturnType.ParameterType + ") {\n" afterword += "runtime.SetFinalizer(ret1, func(ret2 *" + cabiClassName(m.ReturnType.ParameterType) + ") {\n"
afterword += "ret2.Delete()\n" afterword += "ret2.Delete()\n"
afterword += "runtime.KeepAlive(ret2.h)\n" afterword += "runtime.KeepAlive(ret2.h)\n"
afterword += "})\n" afterword += "})\n"

View File

@ -5,6 +5,14 @@ import (
"strings" "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 { type CppParameter struct {
ParameterName string ParameterName string
ParameterType string ParameterType string
@ -15,8 +23,30 @@ type CppParameter struct {
Optional bool Optional bool
} }
func (p *CppParameter) UnderlyingType() string {
if p.TypeAlias != "" {
return p.TypeAlias
}
return p.ParameterType
}
func (p CppParameter) QtClassType() bool { 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) { func (p CppParameter) QListOf() (CppParameter, bool) {

View File

@ -136,6 +136,11 @@ func main() {
astTransformOptional(parsed) astTransformOptional(parsed)
astTransformOverloads(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) processHeaders = append(processHeaders, parsed)
} }