genbindings: support argc/argv idiom used by QApplication ctor

This commit is contained in:
mappu 2024-08-17 14:10:59 +12:00
parent d485d8850e
commit 391c081778
2 changed files with 51 additions and 4 deletions

View File

@ -108,8 +108,23 @@ func (p CppParameter) parameterTypeCgo() string {
func emitParametersGo(params []CppParameter) string {
tmp := make([]string, 0, len(params))
for _, p := range params {
tmp = append(tmp, p.ParameterName+" "+p.RenderTypeGo())
isArgcArgv := false
for i, p := range params {
if i == 0 && IsArgcArgv(params) {
isArgcArgv = true
tmp = append(tmp, "args []string")
} else if i == 1 && isArgcArgv {
// Skip this parameter, already handled
} else {
// Ordinary parameter
tmp = append(tmp, p.ParameterName+" "+p.RenderTypeGo())
}
}
return strings.Join(tmp, ", ")
}
@ -119,8 +134,30 @@ func emitParametersGo2CABIForwarding(m CppMethod) (preamble string, fowarding st
tmp = append(tmp, "this.h")
for _, p := range m.Parameters {
if p.ParameterType == "QString" {
isArgcArgv := false
for i, p := range m.Parameters {
if i == 0 && IsArgcArgv(m.Parameters) {
isArgcArgv = true
// QApplication constructor. Convert 'args' into Qt's wanted types
// Qt has a warning in the docs saying these pointers must be valid
// for the entire lifetype of QApplication, so, malloc + never free
preamble += "// Convert []string to long-lived int& argc, char** argv, never call free()\n"
preamble += "argc := (*C.int)(C.malloc(8))\n"
preamble += "*argc = len(args)\n"
preamble += "argv := (*[0xffff]*C.char)(C.malloc(c.ulong(8 * len(args))))\n"
preamble += "for i := range args {\n"
preamble += "argv[i] = C.CString(" + p.ParameterName + "[i])\n"
preamble += "}\n"
tmp = append(tmp, "argc, argv")
} else if i == 1 && isArgcArgv {
// Skip this parameter, already handled
} else if p.ParameterType == "QString" {
// Go: convert string -> char* and len
// CABI: convert char* and len -> real QString
preamble += p.ParameterName + "_Cstring := C.CString(" + p.ParameterName + ")\n"

View File

@ -63,6 +63,16 @@ type CppMethod struct {
Parameters []CppParameter
}
func IsArgcArgv(params []CppParameter) bool {
// QApplication/QGuiApplication constructors are the only expected example of this.
return (len(params) > 1 &&
params[0].ParameterName == "argc" &&
params[0].ParameterType == "int" &&
params[0].ByRef &&
params[1].ParameterName == "argv" &&
params[1].ParameterType == "char **")
}
func (nm CppMethod) SafeMethodName() string {
// Operator-overload methods have names not representable in binding
// languages. Replace more specific cases first