From 187c0a02ec9c20359e85a1429e893ae668f19110 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Sat, 1 Feb 2025 13:44:06 +1300 Subject: [PATCH] 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. --- cmd/genbindings/clang2il.go | 5 -- cmd/genbindings/emitcabi.go | 140 +++++++++++++++++++++----------- cmd/genbindings/emitgo.go | 115 +++++++++++++++----------- cmd/genbindings/intermediate.go | 3 - 4 files changed, 160 insertions(+), 103 deletions(-) diff --git a/cmd/genbindings/clang2il.go b/cmd/genbindings/clang2il.go index 6c5fca35..b6197809 100644 --- a/cmd/genbindings/clang2il.go +++ b/cmd/genbindings/clang2il.go @@ -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 diff --git a/cmd/genbindings/emitcabi.go b/cmd/genbindings/emitcabi.go index 68025562..ae250d91 100644 --- a/cmd/genbindings/emitcabi.go +++ b/cmd/genbindings/emitcabi.go @@ -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", diff --git a/cmd/genbindings/emitgo.go b/cmd/genbindings/emitgo.go index f16421af..294d80c4 100644 --- a/cmd/genbindings/emitgo.go +++ b/cmd/genbindings/emitgo.go @@ -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() { diff --git a/cmd/genbindings/intermediate.go b/cmd/genbindings/intermediate.go index af5c569b..8ab575c3 100644 --- a/cmd/genbindings/intermediate.go +++ b/cmd/genbindings/intermediate.go @@ -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:]) })