mirror of
https://github.com/mappu/miqt.git
synced 2025-01-05 07:08:39 +00:00
genbindings: many improvements to array marshalling
This commit is contained in:
parent
720da97f59
commit
3121a7c610
@ -202,29 +202,37 @@ func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble s
|
|||||||
gfs.imports["unsafe"] = struct{}{}
|
gfs.imports["unsafe"] = struct{}{}
|
||||||
|
|
||||||
preamble += "// For the C ABI, malloc two C arrays; raw char* pointers and their lengths\n"
|
preamble += "// For the C ABI, malloc two C arrays; raw char* pointers and their lengths\n"
|
||||||
preamble += p.ParameterName + "_CArray := (*[0xffff]*" + listType.parameterTypeCgo() + ")(C.malloc(c.ulong(8 * len(" + p.ParameterName + "))))\n"
|
preamble += p.ParameterName + "_CArray := (*[0xffff]*" + listType.parameterTypeCgo() + ")(C.malloc(C.ulong(8 * len(" + p.ParameterName + "))))\n"
|
||||||
preamble += p.ParameterName + "_Lengths := (*[0xffff]*C.size_t)(C.malloc(c.ulong(8 * len(" + p.ParameterName + "))))\n"
|
preamble += p.ParameterName + "_Lengths := (*[0xffff]C.size_t)(C.malloc(C.ulong(8 * len(" + p.ParameterName + "))))\n"
|
||||||
preamble += "defer C.free(" + p.ParameterName + "_CArray)\n"
|
preamble += "defer C.free(unsafe.Pointer(" + p.ParameterName + "_CArray))\n"
|
||||||
preamble += "defer C.free(" + p.ParameterName + "_Lengths)\n"
|
preamble += "defer C.free(unsafe.Pointer(" + p.ParameterName + "_Lengths))\n"
|
||||||
preamble += "for i := range " + p.ParameterName + "{\n"
|
preamble += "for i := range " + p.ParameterName + "{\n"
|
||||||
preamble += "single_cstring := C.CString(" + p.ParameterName + "[i])\n"
|
preamble += "single_cstring := C.CString(" + p.ParameterName + "[i])\n"
|
||||||
preamble += "defer C.free(unsafe.Pointer(single_cstring))\n"
|
preamble += "defer C.free(unsafe.Pointer(single_cstring))\n"
|
||||||
preamble += p.ParameterName + "_CArray[i] = single_cstring\n"
|
preamble += p.ParameterName + "_CArray[i] = single_cstring\n"
|
||||||
preamble += p.ParameterName + "__Lengths[i] = len(" + p.ParameterName + "[i])\n"
|
preamble += p.ParameterName + "__Lengths[i] = (C.size_t)(len(" + p.ParameterName + "[i]))\n"
|
||||||
preamble += "}\n"
|
preamble += "}\n"
|
||||||
|
|
||||||
tmp = append(tmp, p.ParameterName+"_CArray, "+p.ParameterName+"_Lengths, len("+p.ParameterName+")")
|
tmp = append(tmp, "&"+p.ParameterName+"_CArray[0], "+p.ParameterName+"_Lengths, C.ulong(len("+p.ParameterName+"))")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
preamble += "// For the C ABI, malloc a C array of raw pointers\n"
|
preamble += "// For the C ABI, malloc a C array of raw pointers\n"
|
||||||
preamble += p.ParameterName + "_CArray := (*[0xffff]*" + listType.parameterTypeCgo() + ")(C.malloc(c.ulong(8 * len(" + p.ParameterName + "))))\n"
|
if listType.QtClassType() {
|
||||||
preamble += "defer C.free(" + p.ParameterName + "_CArray)\n"
|
preamble += p.ParameterName + "_CArray := (*[0xffff]*" + listType.parameterTypeCgo() + ")(C.malloc(C.ulong(8 * len(" + p.ParameterName + "))))\n"
|
||||||
|
} else {
|
||||||
|
preamble += p.ParameterName + "_CArray := (*[0xffff]" + listType.parameterTypeCgo() + ")(C.malloc(C.ulong(8 * len(" + p.ParameterName + "))))\n"
|
||||||
|
}
|
||||||
|
preamble += "defer C.free(unsafe.Pointer(" + p.ParameterName + "_CArray))\n"
|
||||||
preamble += "for i := range " + p.ParameterName + "{\n"
|
preamble += "for i := range " + p.ParameterName + "{\n"
|
||||||
|
if listType.QtClassType() {
|
||||||
preamble += p.ParameterName + "_CArray[i] = " + p.ParameterName + "[i].cPointer()\n"
|
preamble += p.ParameterName + "_CArray[i] = " + p.ParameterName + "[i].cPointer()\n"
|
||||||
|
} else {
|
||||||
|
preamble += p.ParameterName + "_CArray[i] = (" + listType.parameterTypeCgo() + ")(" + p.ParameterName + "[i])\n"
|
||||||
|
}
|
||||||
preamble += "}\n"
|
preamble += "}\n"
|
||||||
|
|
||||||
tmp = append(tmp, p.ParameterName+"_CArray, len("+p.ParameterName+")")
|
tmp = append(tmp, "&"+p.ParameterName+"_CArray[0], C.ulong(len("+p.ParameterName+"))")
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if p.Pointer && p.ParameterType == "char" {
|
} else if p.Pointer && p.ParameterType == "char" {
|
||||||
@ -240,7 +248,11 @@ func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble s
|
|||||||
tmp = append(tmp, p.ParameterName+".cPointer()")
|
tmp = append(tmp, p.ParameterName+".cPointer()")
|
||||||
|
|
||||||
} else if p.IntType() || p.ParameterType == "bool" {
|
} else if p.IntType() || p.ParameterType == "bool" {
|
||||||
|
if p.Pointer {
|
||||||
|
tmp = append(tmp, "(*"+p.parameterTypeCgo()+")(unsafe.Pointer("+p.ParameterName+"))") // n.b. This may not work if the integer type conversion was wrong
|
||||||
|
} else {
|
||||||
tmp = append(tmp, "("+p.parameterTypeCgo()+")("+p.ParameterName+")")
|
tmp = append(tmp, "("+p.parameterTypeCgo()+")("+p.ParameterName+")")
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Default
|
// Default
|
||||||
@ -250,9 +262,15 @@ func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble s
|
|||||||
|
|
||||||
if m.ReturnType.ParameterType == "QString" {
|
if m.ReturnType.ParameterType == "QString" {
|
||||||
tmp = append(tmp, "&_out, &_out_Strlen")
|
tmp = append(tmp, "&_out, &_out_Strlen")
|
||||||
} else if _, ok := m.ReturnType.QListOf(); ok {
|
} else if t, ok := m.ReturnType.QListOf(); ok {
|
||||||
|
|
||||||
|
if t.ParameterType == "QString" {
|
||||||
|
// Combo
|
||||||
|
tmp = append(tmp, "&_out, &_out_Lengths, &_out_len")
|
||||||
|
} else {
|
||||||
tmp = append(tmp, "&_out, &_out_len")
|
tmp = append(tmp, "&_out, &_out_len")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return preamble, strings.Join(tmp, ", ")
|
return preamble, strings.Join(tmp, ", ")
|
||||||
}
|
}
|
||||||
@ -317,7 +335,9 @@ import "C"
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
// CGO types only exist within the same Go file, so other Go files can't
|
// CGO types only exist within the same Go file, so other Go files can't
|
||||||
// call this same private ctor function, unless it goes through unsafe.Pointer{}
|
// call this same private ctor function, unless it goes through unsafe.Pointer{}.
|
||||||
|
// This is probably because C types can possibly violate the ODR whereas
|
||||||
|
// that never happens in Go's type system.
|
||||||
gfs.imports["unsafe"] = struct{}{}
|
gfs.imports["unsafe"] = struct{}{}
|
||||||
ret.WriteString(`
|
ret.WriteString(`
|
||||||
func new` + c.ClassName + `_U(h unsafe.Pointer) *` + c.ClassName + ` {
|
func new` + c.ClassName + `_U(h unsafe.Pointer) *` + c.ClassName + ` {
|
||||||
@ -371,16 +391,48 @@ import "C"
|
|||||||
afterword += "return ret"
|
afterword += "return ret"
|
||||||
|
|
||||||
} else if t, ok := m.ReturnType.QListOf(); ok {
|
} else if t, ok := m.ReturnType.QListOf(); ok {
|
||||||
|
gfs.imports["unsafe"] = struct{}{}
|
||||||
shouldReturn = ""
|
shouldReturn = ""
|
||||||
returnTypeDecl = "[]" + t.RenderTypeGo()
|
returnTypeDecl = "[]" + t.RenderTypeGo()
|
||||||
|
|
||||||
preamble += "var _out **" + t.parameterTypeCgo() + " = nil\n"
|
if t.ParameterType == "QString" {
|
||||||
|
// Combo
|
||||||
|
|
||||||
|
preamble += "var _out **C.char = nil\n"
|
||||||
|
preamble += "var _out_Lengths *C.int = nil\n"
|
||||||
preamble += "var _out_len C.size_t = 0\n"
|
preamble += "var _out_len C.size_t = 0\n"
|
||||||
afterword += "ret := make([]" + t.RenderTypeGo() + ", _out_Strlen)\n"
|
afterword += "ret := make([]string, int(_out_len))\n"
|
||||||
afterword += "for i := 0; i < _out_len; i++ {\n"
|
afterword += "_outCast := (*[0xffff]*C.char)(unsafe.Pointer(_out)) // hey ya\n"
|
||||||
afterword += "ret[i] = new" + t.ParameterType + "(_out[i])\n"
|
afterword += "_out_LengthsCast := (*[0xffff]C.int)(unsafe.Pointer(_out_Lengths))\n"
|
||||||
|
afterword += "for i := 0; i < int(_out_len); i++ {\n"
|
||||||
|
afterword += "ret[i] = C.GoStringN(_outCast[i], _out_LengthsCast[i])\n"
|
||||||
afterword += "}\n"
|
afterword += "}\n"
|
||||||
afterword += "C.free(_out)\n"
|
afterword += "C.free(unsafe.Pointer(_out))\n"
|
||||||
|
afterword += "return ret\n"
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if t.QtClassType() {
|
||||||
|
preamble += "var _out **" + t.parameterTypeCgo() + " = nil\n"
|
||||||
|
} else {
|
||||||
|
preamble += "var _out *" + t.parameterTypeCgo() + " = nil\n"
|
||||||
|
}
|
||||||
|
preamble += "var _out_len C.size_t = 0\n"
|
||||||
|
afterword += "ret := make([]" + t.RenderTypeGo() + ", int(_out_len))\n"
|
||||||
|
if t.QtClassType() {
|
||||||
|
afterword += "_outCast := (*[0xffff]*" + t.parameterTypeCgo() + ")(unsafe.Pointer(_out)) // so fresh so clean\n"
|
||||||
|
} else {
|
||||||
|
afterword += "_outCast := (*[0xffff]" + t.parameterTypeCgo() + ")(unsafe.Pointer(_out)) // mrs jackson\n"
|
||||||
|
}
|
||||||
|
afterword += "for i := 0; i < int(_out_len); i++ {\n"
|
||||||
|
if t.QtClassType() {
|
||||||
|
afterword += "ret[i] = new" + t.ParameterType + "(_outCast[i])\n"
|
||||||
|
} else { // plain int type
|
||||||
|
afterword += "ret[i] = (" + t.RenderTypeGo() + ")(_outCast[i])\n"
|
||||||
|
}
|
||||||
|
afterword += "}\n"
|
||||||
|
afterword += "C.free(unsafe.Pointer(_out))\n"
|
||||||
|
afterword += "return ret\n"
|
||||||
|
}
|
||||||
|
|
||||||
} else if m.ReturnType.QtClassType() {
|
} else if m.ReturnType.QtClassType() {
|
||||||
// Construct our Go type based on this inner CABI type
|
// Construct our Go type based on this inner CABI type
|
||||||
|
Loading…
Reference in New Issue
Block a user