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:]) })