Move go name mangling to emitgo

This change helps keep rules for each language separate by moving `go`
rules to `emitgo` while the C bindings stay closer to the original Qt
naming (that already is mostly C-safe).

Although it doesn't practically matter for go, it makes it slightly
easier to reuse the generated code in other languages which have
different keywords and naming conventions.

The cabi generator also gains a few helpers to help keep names
consistent across files which hopefully aids reading the generator code
- it did for me at least;)

The rule that converts under_score to CamelCase is left for another day
since moving it turns out to be more invasive due to name collision
handling - when underscores are kept, there are fewer name conflicts
which ends up causing name changes in  the public go api when done
naively.
This commit is contained in:
Jacek Sieka 2025-02-01 13:44:06 +13:00 committed by mappu
parent e4e9f4dce1
commit 187c0a02ec
4 changed files with 160 additions and 103 deletions

View File

@ -702,11 +702,6 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error {
}
}
// Block reserved Go words, replace with generic parameters
if goReservedWord(parmName) {
parmName += "Val"
}
// Update the name for the existing nth parameter
mm.Parameters[paramCounter].ParameterName = parmName

View File

@ -14,10 +14,58 @@ func cppComment(s string) string {
return "/* " + uncomment.Replace(s) + " */ "
}
func cReservedWord(s string) bool {
// parameter names that appear as properties in Qt, for example
switch s {
case "default": // not language-reserved words, but a binding-reserved words
return true
default:
return false
}
}
func (p CppParameter) cParameterName() string {
// Also make the first letter uppercase so it becomes public in Go
parmName := p.ParameterName
if cReservedWord(parmName) {
parmName += "Val"
}
return parmName
}
func cabiCallbackName(c CppClass, m CppMethod) string {
return "miqt_exec_callback_" + cabiClassName(c.ClassName) + "_" + m.SafeMethodName()
}
func cabiNewName(c CppClass, i int) string {
return cabiClassName(c.ClassName) + `_new` + maybeSuffix(i)
}
func cabiDeleteName(c CppClass) string {
return cabiClassName(c.ClassName) + `_delete`
}
func cabiVirtBaseName(c CppClass) string {
return cabiClassName(c.ClassName) + `_virtbase`
}
func cabiMethodName(c CppClass, m CppMethod) string {
return cabiClassName(c.ClassName) + `_` + m.SafeMethodName()
}
func cabiConnectName(c CppClass, m CppMethod) string {
return cabiClassName(c.ClassName) + `_connect_` + m.SafeMethodName()
}
func cabiVirtualBaseName(c CppClass, m CppMethod) string {
return cabiClassName(c.ClassName) + `_virtualbase_` + m.SafeMethodName()
}
func cabiOverrideVirtualName(c CppClass, m CppMethod) string {
return cabiClassName(c.ClassName) + `_override_virtual_` + m.SafeMethodName()
}
func (p CppParameter) RenderTypeCabi() string {
if p.ParameterType == "QString" {
@ -141,7 +189,7 @@ func (p CppParameter) RenderTypeIntermediateCpp() string {
func emitParametersCpp(m CppMethod) string {
tmp := make([]string, 0, len(m.Parameters))
for _, p := range m.Parameters {
tmp = append(tmp, p.RenderTypeQtCpp()+" "+p.ParameterName)
tmp = append(tmp, p.RenderTypeQtCpp()+" "+p.cParameterName())
}
return strings.Join(tmp, `, `)
@ -150,7 +198,7 @@ func emitParametersCpp(m CppMethod) string {
func emitParameterNames(m CppMethod) string {
tmp := make([]string, 0, len(m.Parameters))
for _, p := range m.Parameters {
tmp = append(tmp, p.ParameterName)
tmp = append(tmp, p.cParameterName())
}
return strings.Join(tmp, `, `)
@ -178,7 +226,7 @@ func emitParametersCabi(m CppMethod, selfType string) string {
}
for _, p := range m.Parameters {
tmp = append(tmp, p.RenderTypeCabi()+" "+p.ParameterName)
tmp = append(tmp, p.RenderTypeCabi()+" "+p.cParameterName())
}
return strings.Join(tmp, ", ")
@ -203,28 +251,28 @@ func makeNamePrefix(in string) string {
func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, forwarding string) {
nameprefix := makeNamePrefix(p.ParameterName)
nameprefix := makeNamePrefix(p.cParameterName())
if p.ParameterType == "QString" {
// The CABI received parameter is a struct miqt_string, passed by value
// C++ needs it as a QString. Create one on the stack for automatic cleanup
// The caller will free the miqt_string
preamble += indent + "QString " + nameprefix + "_QString = QString::fromUtf8(" + p.ParameterName + ".data, " + p.ParameterName + ".len);\n"
preamble += indent + "QString " + nameprefix + "_QString = QString::fromUtf8(" + p.cParameterName() + ".data, " + p.cParameterName() + ".len);\n"
return preamble, nameprefix + "_QString"
} else if p.ParameterType == "QByteArray" {
// The caller will free the miqt_string data
// This ctor makes a deep copy, on the stack which will be dtor'd by RAII
preamble += indent + "QByteArray " + nameprefix + "_QByteArray(" + p.ParameterName + ".data, " + p.ParameterName + ".len);\n"
preamble += indent + "QByteArray " + nameprefix + "_QByteArray(" + p.cParameterName() + ".data, " + p.cParameterName() + ".len);\n"
return preamble, nameprefix + "_QByteArray"
} else if listType, ok := p.QListOf(); ok {
preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QList;\n"
preamble += indent + nameprefix + "_QList.reserve(" + p.ParameterName + ".len);\n"
preamble += indent + nameprefix + "_QList.reserve(" + p.cParameterName() + ".len);\n"
preamble += indent + listType.RenderTypeCabi() + "* " + nameprefix + "_arr = static_cast<" + listType.RenderTypeCabi() + "*>(" + p.ParameterName + ".data);\n"
preamble += indent + "for(size_t i = 0; i < " + p.ParameterName + ".len; ++i) {\n"
preamble += indent + listType.RenderTypeCabi() + "* " + nameprefix + "_arr = static_cast<" + listType.RenderTypeCabi() + "*>(" + p.cParameterName() + ".data);\n"
preamble += indent + "for(size_t i = 0; i < " + p.cParameterName() + ".len; ++i) {\n"
listType.ParameterName = nameprefix + "_arr[i]"
addPre, addFwd := emitCABI2CppForwarding(listType, indent+"\t")
@ -246,12 +294,12 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
// This container may be a QMap or a QHash
// QHash supports .reserve(), but QMap doesn't
if strings.HasPrefix(p.ParameterType, "QHash<") {
preamble += indent + nameprefix + "_QMap.reserve(" + p.ParameterName + ".len);\n"
preamble += indent + nameprefix + "_QMap.reserve(" + p.cParameterName() + ".len);\n"
}
preamble += indent + kType.RenderTypeCabi() + "* " + nameprefix + "_karr = static_cast<" + kType.RenderTypeCabi() + "*>(" + p.ParameterName + ".keys);\n"
preamble += indent + vType.RenderTypeCabi() + "* " + nameprefix + "_varr = static_cast<" + vType.RenderTypeCabi() + "*>(" + p.ParameterName + ".values);\n"
preamble += indent + "for(size_t i = 0; i < " + p.ParameterName + ".len; ++i) {\n"
preamble += indent + kType.RenderTypeCabi() + "* " + nameprefix + "_karr = static_cast<" + kType.RenderTypeCabi() + "*>(" + p.cParameterName() + ".keys);\n"
preamble += indent + vType.RenderTypeCabi() + "* " + nameprefix + "_varr = static_cast<" + vType.RenderTypeCabi() + "*>(" + p.cParameterName() + ".values);\n"
preamble += indent + "for(size_t i = 0; i < " + p.cParameterName() + ".len; ++i) {\n"
kType.ParameterName = nameprefix + "_karr[i]"
addPreK, addFwdK := emitCABI2CppForwarding(kType, indent+"\t")
@ -269,8 +317,8 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
} else if kType, vType, ok := p.QPairOf(); ok {
preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QPair;\n"
preamble += indent + kType.RenderTypeCabi() + "* " + nameprefix + "_first_arr = static_cast<" + kType.RenderTypeCabi() + "*>(" + p.ParameterName + ".keys);\n"
preamble += indent + vType.RenderTypeCabi() + "* " + nameprefix + "_second_arr = static_cast<" + vType.RenderTypeCabi() + "*>(" + p.ParameterName + ".values);\n"
preamble += indent + kType.RenderTypeCabi() + "* " + nameprefix + "_first_arr = static_cast<" + kType.RenderTypeCabi() + "*>(" + p.cParameterName() + ".keys);\n"
preamble += indent + vType.RenderTypeCabi() + "* " + nameprefix + "_second_arr = static_cast<" + vType.RenderTypeCabi() + "*>(" + p.cParameterName() + ".values);\n"
kType.ParameterName = nameprefix + "_first_arr[0]"
addPreK, addFwdK := emitCABI2CppForwarding(kType, indent+"\t")
@ -286,7 +334,7 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
return preamble, nameprefix + "_QPair"
} else if p.IsFlagType() || p.IntType() || p.IsKnownEnum() {
castSrc := p.ParameterName
castSrc := p.cParameterName()
castType := p.RenderTypeQtCpp()
if p.ByRef { // e.g. QDataStream::operator>>() overloads
@ -294,7 +342,7 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
}
if p.QtCppOriginalType != nil && p.QtCppOriginalType.Const != p.Const {
return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(const_cast<" + p.RenderTypeIntermediateCpp() + ">(" + p.ParameterName + "))"
return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(const_cast<" + p.RenderTypeIntermediateCpp() + ">(" + p.cParameterName() + "))"
}
if p.ParameterType == "qint64" ||
@ -326,25 +374,25 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
// By ref and by pointer
// This happens for QDataStream &QDataStream::operator>>(char *&s)
// We are only using one level of indirection
return preamble, p.ParameterName
return preamble, p.cParameterName()
} else {
// By ref and not by pointer
// We changed RenderTypeCabi() to render this as a pointer
// Need to dereference so we can pass as reference to the actual Qt C++ function
//tmp = append(tmp, "*"+p.ParameterName)
return preamble, "*" + p.ParameterName
//tmp = append(tmp, "*"+p.cParameterName())
return preamble, "*" + p.cParameterName()
}
} else if p.QtClassType() && !p.Pointer {
// CABI takes all Qt types by pointer, even if C++ wants them by value
// Dereference the passed-in pointer
if strings.Contains(p.ParameterName, `[`) {
return preamble, "*(" + p.ParameterName + ")" // Extra brackets aren't necessary, just nice
if strings.Contains(p.cParameterName(), `[`) {
return preamble, "*(" + p.cParameterName() + ")" // Extra brackets aren't necessary, just nice
}
return preamble, "*" + p.ParameterName
return preamble, "*" + p.cParameterName()
} else {
return preamble, p.ParameterName
return preamble, p.cParameterName()
}
}
@ -362,7 +410,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
shouldReturn = shouldReturn[len(indent):]
namePrefix := makeNamePrefix(p.ParameterName)
namePrefix := makeNamePrefix(p.cParameterName())
if p.Void() {
shouldReturn = ""
@ -724,15 +772,15 @@ extern "C" {
for _, c := range src.Classes {
methodPrefixName := cabiClassName(c.ClassName)
className := cabiClassName(c.ClassName)
for i, ctor := range c.Ctors {
ret.WriteString(fmt.Sprintf("%s* %s_new%s(%s);\n", methodPrefixName, methodPrefixName, maybeSuffix(i), emitParametersCabiConstructor(&c, &ctor)))
ret.WriteString(fmt.Sprintf("%s* %s(%s);\n", className, cabiNewName(c, i), emitParametersCabiConstructor(&c, &ctor)))
}
if len(c.DirectInheritClassInfo()) > 0 {
ret.WriteString(
"void " + methodPrefixName + "_virtbase(" + methodPrefixName + "* src",
"void " + cabiVirtBaseName(c) + "(" + className + "* src",
)
for _, baseClass := range c.DirectInheritClassInfo() {
ret.WriteString(", " + cabiClassName(baseClass.Class.ClassName) + "** outptr_" + cabiClassName(baseClass.Class.ClassName))
@ -741,22 +789,22 @@ extern "C" {
}
for _, m := range c.Methods {
ret.WriteString(fmt.Sprintf("%s %s_%s(%s);\n", m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+methodPrefixName+"*")))
ret.WriteString(fmt.Sprintf("%s %s(%s);\n", m.ReturnType.RenderTypeCabi(), cabiMethodName(c, m), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+className+"*")))
if m.IsSignal {
ret.WriteString(fmt.Sprintf("%s %s_connect_%s(%s* self, intptr_t slot);\n", m.ReturnType.RenderTypeCabi(), methodPrefixName, m.SafeMethodName(), methodPrefixName))
ret.WriteString(fmt.Sprintf("%s %s(%s* self, intptr_t slot);\n", m.ReturnType.RenderTypeCabi(), cabiConnectName(c, m), className))
}
}
for _, m := range c.VirtualMethods() {
ret.WriteString(fmt.Sprintf("bool %s_override_virtual_%s(%s* self, intptr_t slot);\n", methodPrefixName, m.SafeMethodName(), "void" /*methodPrefixName*/))
ret.WriteString(fmt.Sprintf("bool %s(%s* self, intptr_t slot);\n", cabiOverrideVirtualName(c, m), "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(%s);\n", m.ReturnType.RenderTypeCabi(), cabiVirtualBaseName(c, m), emitParametersCabi(m, ifv(m.IsConst, "const ", "")+"void" /*className*/ +"*")))
}
// delete
if c.CanDelete {
ret.WriteString(fmt.Sprintf("void %s_Delete(%s* self);\n", methodPrefixName, methodPrefixName))
ret.WriteString(fmt.Sprintf("void %s(%s* self);\n", cabiDeleteName(c), className))
}
ret.WriteString("\n")
@ -765,7 +813,7 @@ extern "C" {
ret.WriteString(
`#ifdef __cplusplus
} /* extern C */
#endif
#endif
#endif
`)
@ -781,7 +829,7 @@ func emitParametersCabiConstructor(c *CppClass, ctor *CppMethod) string {
slist := make([]string, 0, len(ctor.Parameters))
for _, p := range ctor.Parameters {
slist = append(slist, p.RenderTypeCabi()+" "+p.ParameterName)
slist = append(slist, p.RenderTypeCabi()+" "+p.cParameterName())
}
return strings.Join(slist, `, `)
@ -943,7 +991,7 @@ extern "C" {
var signalCode string
for i, p := range m.Parameters {
signalCode += emitAssignCppToCabi(fmt.Sprintf("\t\t%s sigval%d = ", p.RenderTypeCabi(), i+1), p, p.ParameterName)
signalCode += emitAssignCppToCabi(fmt.Sprintf("\t\t%s sigval%d = ", p.RenderTypeCabi(), i+1), p, p.cParameterName())
paramArgs = append(paramArgs, fmt.Sprintf("sigval%d", i+1))
}
@ -970,7 +1018,7 @@ extern "C" {
var parametersCabi []string
for _, p := range m.Parameters {
parametersCabi = append(parametersCabi, p.RenderTypeCabi()+" "+p.ParameterName)
parametersCabi = append(parametersCabi, p.RenderTypeCabi()+" "+p.cParameterName())
}
vbpreamble, vbforwarding := emitParametersCABI2CppForwarding(m.Parameters, "\t\t")
@ -1001,7 +1049,7 @@ extern "C" {
preamble, forwarding := emitParametersCABI2CppForwarding(ctor.Parameters, "\t")
ret.WriteString(
cabiClassName(c.ClassName) + "* " + methodPrefixName + "_new" + maybeSuffix(i) + "(" + emitParametersCabiConstructor(&c, &ctor) + ") {\n",
cabiClassName(c.ClassName) + "* " + cabiNewName(c, i) + "(" + emitParametersCabiConstructor(&c, &ctor) + ") {\n",
)
if ctor.LinuxOnly {
@ -1035,7 +1083,7 @@ extern "C" {
// need the base pointers to call base methods from CGO
if len(c.DirectInheritClassInfo()) > 0 {
ret.WriteString(
"void " + methodPrefixName + "_virtbase(" + methodPrefixName + "* src",
"void " + cabiVirtBaseName(c) + "(" + methodPrefixName + "* src",
)
for _, baseClass := range c.DirectInheritClassInfo() {
ret.WriteString(", " + baseClass.Class.ClassName + "** outptr_" + cabiClassName(baseClass.Class.ClassName))
@ -1141,15 +1189,15 @@ extern "C" {
var signalCode string
for i, p := range m.Parameters {
signalCode += emitAssignCppToCabi(fmt.Sprintf("\t\t%s sigval%d = ", p.RenderTypeCabi(), i+1), p, p.ParameterName)
signalCode += emitAssignCppToCabi(fmt.Sprintf("\t\t%s sigval%d = ", p.RenderTypeCabi(), i+1), p, p.cParameterName())
paramArgs = append(paramArgs, fmt.Sprintf("sigval%d", i+1))
paramArgDefs = append(paramArgDefs, p.RenderTypeCabi()+" "+p.ParameterName)
paramArgDefs = append(paramArgDefs, p.RenderTypeCabi()+" "+p.cParameterName())
}
signalCode += "\t\t" + cabiCallbackName(c, m) + "(" + strings.Join(paramArgs, `, `) + ");\n"
ret.WriteString(
`void ` + methodPrefixName + `_connect_` + m.SafeMethodName() + `(` + methodPrefixName + `* self, intptr_t slot) {` + "\n" +
`void ` + cabiConnectName(c, m) + `(` + methodPrefixName + `* self, intptr_t slot) {` + "\n" +
"\t" + cppClassName + `::connect(self, ` + exactSignal + `, self, [=](` + emitParametersCpp(m) + `) {` + "\n" +
signalCode +
"\t});\n" +
@ -1170,7 +1218,7 @@ extern "C" {
// upclass it
ret.WriteString(
`bool ` + methodPrefixName + `_override_virtual_` + m.SafeMethodName() + `(void* self, intptr_t slot) {` + "\n" +
`bool ` + cabiOverrideVirtualName(c, m) + `(void* self, intptr_t slot) {` + "\n" +
"\t" + cppClassName + "* self_cast = dynamic_cast<" + cppClassName + "*>( (" + cabiClassName(c.ClassName) + "*)(self) );\n" +
"\tif (self_cast == nullptr) {\n" +
"\t\treturn false;\n" +
@ -1195,7 +1243,7 @@ extern "C" {
var parameterNames []string
for _, param := range m.Parameters {
parameterNames = append(parameterNames, param.ParameterName)
parameterNames = append(parameterNames, param.cParameterName())
}
// callTarget is an rvalue representing the full C++ function call.
@ -1204,7 +1252,7 @@ extern "C" {
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 ", "")+"void*") + ") {\n" +
m.ReturnType.RenderTypeCabi() + " " + cabiVirtualBaseName(c, m) + "(" + emitParametersCabi(m, ifv(m.IsConst, "const ", "")+"void*") + ") {\n" +
"\t" + ifv(m.ReturnType.Void(), "", "return ") + callTarget + ";\n" +
"}\n" +
"\n",
@ -1219,7 +1267,7 @@ extern "C" {
// we can delete from the self ptr without any dynamic_cast<>
if c.CanDelete {
ret.WriteString(
"void " + methodPrefixName + "_Delete(" + methodPrefixName + "* self) {\n" +
"void " + cabiDeleteName(c) + "(" + methodPrefixName + "* self) {\n" +
"\tdelete self;\n" +
"}\n" +
"\n",

View File

@ -22,6 +22,23 @@ func goReservedWord(s string) bool {
}
}
func (nm CppMethod) goMethodName() string {
// Also make the first letter uppercase so it becomes public in Go
tmp := nm.SafeMethodName()
tmp = titleCase(tmp)
return tmp
}
func (p CppParameter) goParameterName() string {
// Also make the first letter uppercase so it becomes public in Go
parmName := p.ParameterName
if goReservedWord(parmName) {
parmName += "Val"
}
return parmName
}
func (p CppParameter) RenderTypeGo(gfs *goFileState) string {
if p.Pointer && p.ParameterType == "char" {
return "string"
@ -247,7 +264,7 @@ func (gfs *goFileState) emitParametersGo(params []CppParameter) string {
} else {
// Ordinary parameter
tmp = append(tmp, p.ParameterName+" "+p.RenderTypeGo(gfs))
tmp = append(tmp, p.goParameterName()+" "+p.RenderTypeGo(gfs))
}
}
@ -312,7 +329,7 @@ func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble s
func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble string, rvalue string) {
nameprefix := makeNamePrefix(p.ParameterName)
nameprefix := makeNamePrefix(p.goParameterName())
if p.ParameterType == "QString" {
// Go: convert string -> miqt_string*
@ -320,8 +337,8 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
gfs.imports["unsafe"] = struct{}{}
preamble += nameprefix + "_ms := C.struct_miqt_string{}\n"
preamble += nameprefix + "_ms.data = C.CString(" + p.ParameterName + ")\n"
preamble += nameprefix + "_ms.len = C.size_t(len(" + p.ParameterName + "))\n"
preamble += nameprefix + "_ms.data = C.CString(" + p.goParameterName() + ")\n"
preamble += nameprefix + "_ms.len = C.size_t(len(" + p.goParameterName() + "))\n"
preamble += "defer C.free(unsafe.Pointer(" + nameprefix + "_ms.data))\n"
rvalue = nameprefix + "_ms"
@ -333,12 +350,12 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
gfs.imports["unsafe"] = struct{}{}
preamble += nameprefix + "_alias := C.struct_miqt_string{}\n"
preamble += "if len(" + p.ParameterName + ") > 0 {\n"
preamble += nameprefix + "_alias.data = (*C.char)(unsafe.Pointer(&" + p.ParameterName + "[0]))\n"
preamble += "if len(" + p.goParameterName() + ") > 0 {\n"
preamble += nameprefix + "_alias.data = (*C.char)(unsafe.Pointer(&" + p.goParameterName() + "[0]))\n"
preamble += "} else {\n"
preamble += nameprefix + "_alias.data = (*C.char)(unsafe.Pointer(nil))\n"
preamble += "}\n"
preamble += nameprefix + "_alias.len = C.size_t(len(" + p.ParameterName + "))\n"
preamble += nameprefix + "_alias.len = C.size_t(len(" + p.goParameterName() + "))\n"
rvalue = nameprefix + "_alias"
@ -351,18 +368,18 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
mallocSize := listType.mallocSizeCgoExpression()
preamble += nameprefix + "_CArray := (*[0xffff]" + listType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + mallocSize + " * len(" + p.ParameterName + "))))\n"
preamble += nameprefix + "_CArray := (*[0xffff]" + listType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + mallocSize + " * len(" + p.goParameterName() + "))))\n"
preamble += "defer C.free(unsafe.Pointer(" + nameprefix + "_CArray))\n"
preamble += "for i := range " + p.ParameterName + "{\n"
preamble += "for i := range " + p.goParameterName() + "{\n"
listType.ParameterName = p.ParameterName + "[i]"
listType.ParameterName = p.goParameterName() + "[i]"
addPreamble, innerRvalue := gfs.emitParameterGo2CABIForwarding(listType)
preamble += addPreamble
preamble += nameprefix + "_CArray[i] = " + innerRvalue + "\n"
preamble += "}\n"
preamble += nameprefix + "_ma := C.struct_miqt_array{len: C.size_t(len(" + p.ParameterName + ")), data: unsafe.Pointer(" + nameprefix + "_CArray)}\n"
preamble += nameprefix + "_ma := C.struct_miqt_array{len: C.size_t(len(" + p.goParameterName() + ")), data: unsafe.Pointer(" + nameprefix + "_CArray)}\n"
rvalue = nameprefix + "_ma"
@ -374,15 +391,15 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
gfs.imports["unsafe"] = struct{}{}
preamble += nameprefix + "_Keys_CArray := (*[0xffff]" + kType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + kType.mallocSizeCgoExpression() + " * len(" + p.ParameterName + "))))\n"
preamble += nameprefix + "_Keys_CArray := (*[0xffff]" + kType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + kType.mallocSizeCgoExpression() + " * len(" + p.goParameterName() + "))))\n"
preamble += "defer C.free(unsafe.Pointer(" + nameprefix + "_Keys_CArray))\n"
preamble += nameprefix + "_Values_CArray := (*[0xffff]" + vType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + vType.mallocSizeCgoExpression() + " * len(" + p.ParameterName + "))))\n"
preamble += nameprefix + "_Values_CArray := (*[0xffff]" + vType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + vType.mallocSizeCgoExpression() + " * len(" + p.goParameterName() + "))))\n"
preamble += "defer C.free(unsafe.Pointer(" + nameprefix + "_Values_CArray))\n"
preamble += nameprefix + "_ctr := 0\n"
preamble += "for " + nameprefix + "_k, " + nameprefix + "_v := range " + p.ParameterName + "{\n"
preamble += "for " + nameprefix + "_k, " + nameprefix + "_v := range " + p.goParameterName() + "{\n"
kType.ParameterName = nameprefix + "_k"
addPreamble, innerRvalue := gfs.emitParameterGo2CABIForwarding(kType)
@ -398,7 +415,7 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
preamble += "}\n"
preamble += nameprefix + "_mm := C.struct_miqt_map{\nlen: C.size_t(len(" + p.ParameterName + ")),\nkeys: unsafe.Pointer(" + nameprefix + "_Keys_CArray),\nvalues: unsafe.Pointer(" + nameprefix + "_Values_CArray),\n}\n"
preamble += nameprefix + "_mm := C.struct_miqt_map{\nlen: C.size_t(len(" + p.goParameterName() + ")),\nkeys: unsafe.Pointer(" + nameprefix + "_Keys_CArray),\nvalues: unsafe.Pointer(" + nameprefix + "_Values_CArray),\n}\n"
rvalue = nameprefix + "_mm"
@ -413,12 +430,12 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
preamble += nameprefix + "_Second_CArray := (*[0xffff]" + vType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + vType.mallocSizeCgoExpression() + ")))\n"
preamble += "defer C.free(unsafe.Pointer(" + nameprefix + "_Second_CArray))\n"
kType.ParameterName = p.ParameterName + ".First"
kType.ParameterName = p.goParameterName() + ".First"
addPreamble, innerRvalue := gfs.emitParameterGo2CABIForwarding(kType)
preamble += addPreamble
preamble += nameprefix + "_First_CArray[0] = " + innerRvalue + "\n"
vType.ParameterName = p.ParameterName + ".Second"
vType.ParameterName = p.goParameterName() + ".Second"
addPreamble, innerRvalue = gfs.emitParameterGo2CABIForwarding(vType)
preamble += addPreamble
preamble += nameprefix + "_Second_CArray[0] = " + innerRvalue + "\n"
@ -430,7 +447,7 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
} else if p.Pointer && p.ParameterType == "char" {
// Single char* argument
gfs.imports["unsafe"] = struct{}{}
preamble += nameprefix + "_Cstring := C.CString(" + p.ParameterName + ")\n"
preamble += nameprefix + "_Cstring := C.CString(" + p.goParameterName() + ")\n"
preamble += "defer C.free(unsafe.Pointer(" + nameprefix + "_Cstring))\n"
rvalue = nameprefix + "_Cstring"
@ -442,23 +459,23 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
if classInfo, ok := KnownClassnames[p.ParameterType]; ok && gfs.currentPackageName != classInfo.PackageName {
// Cross-package
rvalue = "(" + p.parameterTypeCgo() + ")(" + p.ParameterName + ".UnsafePointer())"
rvalue = "(" + p.parameterTypeCgo() + ")(" + p.goParameterName() + ".UnsafePointer())"
} else {
// Same package
rvalue = p.ParameterName + ".cPointer()"
rvalue = p.goParameterName() + ".cPointer()"
}
} else if p.IntType() || p.IsFlagType() || p.IsKnownEnum() || p.ParameterType == "bool" {
if p.Pointer || p.ByRef {
gfs.imports["unsafe"] = struct{}{}
rvalue = "(" + p.parameterTypeCgo() + ")(unsafe.Pointer(" + p.ParameterName + "))" // n.b. This may not work if the integer type conversion was wrong
rvalue = "(" + p.parameterTypeCgo() + ")(unsafe.Pointer(" + p.goParameterName() + "))" // n.b. This may not work if the integer type conversion was wrong
} else {
rvalue = "(" + p.parameterTypeCgo() + ")(" + p.ParameterName + ")"
rvalue = "(" + p.parameterTypeCgo() + ")(" + p.goParameterName() + ")"
}
} else {
// Default
rvalue = p.ParameterName
rvalue = p.goParameterName()
}
return preamble, rvalue
@ -468,7 +485,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
shouldReturn := assignExpr // "return "
afterword := ""
namePrefix := makeNamePrefix(rt.ParameterName)
namePrefix := makeNamePrefix(rt.goParameterName())
if rt.Void() {
shouldReturn = ""
@ -644,7 +661,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
return assignExpr + "(" + rt.RenderTypeGo(gfs) + ")(" + rvalue + ")\n"
} else {
panic(fmt.Sprintf("emitgo::emitCabiToGo missing type handler for parameter %+v", rt))
return "int /* TODO */" //panic(fmt.Sprintf("emitgo::emitCabiToGo missing type handler for parameter %+v", rt))
}
}
@ -849,19 +866,19 @@ import "C"
}
// Populate outptr pointers
ret.WriteString("C." + cabiClassName(c.ClassName) + "_virtbase(h" + xbaseParams + ")\n")
ret.WriteString("C." + cabiVirtBaseName(c) + "(h" + xbaseParams + ")\n")
}
ret.WriteString(`
return &` + goClassName + `{` + localInit + `}
}
// UnsafeNew` + goClassName + ` constructs the type using only unsafe pointers.
func UnsafeNew` + goClassName + `(h unsafe.Pointer) *` + goClassName + ` {
return new` + goClassName + `( (*C.` + goClassName + `)(h) )
}
`)
//
@ -888,10 +905,10 @@ import "C"
// Call Cgo constructor
ret.WriteString(`
return new` + goClassName + `(C.` + goClassName + `_new` + maybeSuffix(i) + `(` + forwarding + `))
ret.WriteString(`
return new` + goClassName + `(C.` + cabiNewName(c, i) + `(` + forwarding + `))
}
`)
}
@ -906,13 +923,13 @@ import "C"
returnTypeDecl := m.ReturnType.renderReturnTypeGo(&gfs)
rvalue := `C.` + goClassName + `_` + m.SafeMethodName() + `(` + forwarding + `)`
rvalue := `C.` + cabiMethodName(c, m) + `(` + forwarding + `)`
returnFunc := gfs.emitCabiToGo("return ", m.ReturnType, rvalue)
receiverAndMethod := `(this *` + goClassName + `) ` + m.SafeMethodName()
receiverAndMethod := `(this *` + goClassName + `) ` + m.goMethodName()
if m.IsStatic {
receiverAndMethod = goClassName + `_` + m.SafeMethodName()
receiverAndMethod = goClassName + `_` + m.goMethodName()
}
ret.WriteString(`
@ -943,16 +960,16 @@ import "C"
conversion = "// Convert all CABI parameters to Go parameters\n"
}
for i, pp := range m.Parameters {
cgoNamedParams = append(cgoNamedParams, pp.ParameterName+" "+pp.parameterTypeCgo())
cgoNamedParams = append(cgoNamedParams, pp.goParameterName()+" "+pp.parameterTypeCgo())
paramNames = append(paramNames, fmt.Sprintf("slotval%d", i+1))
conversion += gfs.emitCabiToGo(fmt.Sprintf("slotval%d := ", i+1), pp, pp.ParameterName) + "\n"
conversion += gfs.emitCabiToGo(fmt.Sprintf("slotval%d := ", i+1), pp, pp.goParameterName()) + "\n"
}
goCbType := `func(` + gfs.emitParametersGo(m.Parameters) + `)`
callbackName := cabiCallbackName(c, m)
ret.WriteString(`func (this *` + goClassName + `) On` + m.SafeMethodName() + `(slot ` + goCbType + `) {
C.` + goClassName + `_connect_` + m.SafeMethodName() + `(this.h, C.intptr_t(cgo.NewHandle(slot)) )
ret.WriteString(`func (this *` + goClassName + `) On` + m.goMethodName() + `(slot ` + goCbType + `) {
C.` + cabiConnectName(c, m) + `(this.h, C.intptr_t(cgo.NewHandle(slot)) )
}
//export ` + callbackName + `
@ -961,9 +978,9 @@ import "C"
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
` + conversion + `
gofunc(` + strings.Join(paramNames, `, `) + ` )
}
@ -987,9 +1004,9 @@ import "C"
returnTypeDecl := m.ReturnType.renderReturnTypeGo(&gfs)
ret.WriteString(`
func (this *` + goClassName + `) callVirtualBase_` + m.SafeMethodName() + `(` + gfs.emitParametersGo(m.Parameters) + `) ` + returnTypeDecl + ` {
func (this *` + goClassName + `) callVirtualBase_` + m.goMethodName() + `(` + gfs.emitParametersGo(m.Parameters) + `) ` + returnTypeDecl + ` {
` + preamble + `
` + gfs.emitCabiToGo("return ", m.ReturnType, `C.`+goClassName+`_virtualbase_`+m.SafeMethodName()+`(`+forwarding+`)`) + `
` + gfs.emitCabiToGo("return ", m.ReturnType, `C.`+cabiVirtualBaseName(c, m)+`(`+forwarding+`)`) + `
}
`)
@ -1004,7 +1021,7 @@ import "C"
var cgoNamedParams []string
var paramNames []string
if !m.IsPureVirtual {
paramNames = append(paramNames, "(&"+goClassName+"{h: self}).callVirtualBase_"+m.SafeMethodName())
paramNames = append(paramNames, "(&"+goClassName+"{h: self}).callVirtualBase_"+m.goMethodName())
}
conversion := ""
@ -1012,10 +1029,10 @@ import "C"
conversion = "// Convert all CABI parameters to Go parameters\n"
}
for i, pp := range m.Parameters {
cgoNamedParams = append(cgoNamedParams, pp.ParameterName+" "+pp.parameterTypeCgo())
cgoNamedParams = append(cgoNamedParams, pp.goParameterName()+" "+pp.parameterTypeCgo())
paramNames = append(paramNames, fmt.Sprintf("slotval%d", i+1))
conversion += gfs.emitCabiToGo(fmt.Sprintf("slotval%d := ", i+1), pp, pp.ParameterName) + "\n"
conversion += gfs.emitCabiToGo(fmt.Sprintf("slotval%d := ", i+1), pp, pp.goParameterName()) + "\n"
}
cabiReturnType := m.ReturnType.parameterTypeCgo()
@ -1036,7 +1053,7 @@ import "C"
goCbType += `) ` + m.ReturnType.renderReturnTypeGo(&gfs)
callbackName := cabiCallbackName(c, m)
ret.WriteString(`func (this *` + goClassName + `) On` + m.SafeMethodName() + `(slot ` + goCbType + `) {
ok := C.` + goClassName + `_override_virtual_` + m.SafeMethodName() + `(unsafe.Pointer(this.h), C.intptr_t(cgo.NewHandle(slot)) )
ok := C.` + cabiOverrideVirtualName(c, m) + `(unsafe.Pointer(this.h), C.intptr_t(cgo.NewHandle(slot)) )
if !ok {
panic("miqt: can only override virtual methods for directly constructed types")
}
@ -1048,7 +1065,7 @@ import "C"
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}
`)
ret.WriteString(conversion + "\n")
if cabiReturnType == "" {
@ -1075,9 +1092,9 @@ import "C"
ret.WriteString(`
// Delete this object from C++ memory.
func (this *` + goClassName + `) Delete() {
C.` + goClassName + `_Delete(this.h)
C.` + cabiDeleteName(c) + `(this.h)
}
// GoGC adds a Go Finalizer to this pointer, so that it will be deleted
// from C++ memory once it is unreachable from Go memory.
func (this *` + goClassName + `) GoGC() {

View File

@ -351,9 +351,6 @@ func (nm CppMethod) SafeMethodName() string {
)
tmp = replacer.Replace(tmp)
// Also make the first letter uppercase so it becomes public in Go
tmp = titleCase(tmp)
// Replace spaces (e.g. `operator long long` with CamelCase
tmp = regexp.MustCompile(` ([a-zA-Z])`).ReplaceAllStringFunc(tmp, func(match string) string { return strings.ToUpper(match[1:]) })