genbindings/qbytearray: project as []byte

This commit is contained in:
mappu 2024-10-19 12:24:49 +13:00
parent 434c45273a
commit bb0132e0d5
4 changed files with 66 additions and 2 deletions

View File

@ -11,6 +11,9 @@ func (p CppParameter) RenderTypeCabi() string {
if p.ParameterType == "QString" {
return "struct miqt_string"
} else if p.ParameterType == "QByteArray" {
return "struct miqt_string"
} else if _, ok := p.QListOf(); ok {
return "struct miqt_array*"
@ -148,6 +151,9 @@ func emitParametersCabi(m CppMethod, selfType string) string {
if p.ParameterType == "QString" {
tmp = append(tmp, "struct miqt_string "+p.ParameterName)
} else if p.ParameterType == "QByteArray" {
tmp = append(tmp, "struct miqt_string "+p.ParameterName)
} else if t, ok := p.QListOf(); ok {
tmp = append(tmp, "struct miqt_array* /* of "+t.RenderTypeCabi()+" */ "+p.ParameterName)
@ -203,6 +209,12 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
preamble += indent + "QString " + nameprefix + "_QString = QString::fromUtf8(" + p.ParameterName + ".data, " + p.ParameterName + ".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"
return preamble, nameprefix + "_QByteArray"
} else if listType, ok := p.QListOf(); ok {
preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QList;\n"
@ -322,6 +334,18 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
afterCall += indent + "memcpy(" + namePrefix + "_ms.data, " + namePrefix + "_b.data(), " + namePrefix + "_ms.len);\n"
afterCall += indent + assignExpression + namePrefix + "_ms;\n"
} else if p.ParameterType == "QByteArray" {
// C++ has given us a QByteArray. CABI needs this as a struct miqt_string
// Do not free the data, the caller will free it
shouldReturn = ifv(p.Const, "const ", "") + "QByteArray " + p.ParameterName + "_qb = "
afterCall += indent + "struct miqt_string " + namePrefix + "_ms;\n"
afterCall += indent + namePrefix + "_ms.len = " + namePrefix + "_qb.length();\n"
afterCall += indent + namePrefix + "_ms.data = static_cast<char*>(malloc(" + namePrefix + "_ms.len));\n"
afterCall += indent + "memcpy(" + namePrefix + "_ms.data, " + namePrefix + "_qb.data(), " + namePrefix + "_ms.len);\n"
afterCall += indent + assignExpression + namePrefix + "_ms;\n"
} else if t, ok := p.QListOf(); ok {
// In some cases rvalue is a function call and the temporary

View File

@ -26,6 +26,9 @@ func (p CppParameter) RenderTypeGo(gfs *goFileState) string {
if p.ParameterType == "QString" {
return "string"
}
if p.ParameterType == "QByteArray" {
return "[]byte"
}
if t, ok := p.QListOf(); ok {
return "[]" + t.RenderTypeGo(gfs)
@ -145,6 +148,10 @@ func (p CppParameter) parameterTypeCgo() string {
return "C.struct_miqt_string"
}
if p.ParameterType == "QByteArray" {
return "C.struct_miqt_string"
}
if _, ok := p.QListOf(); ok {
return "*C.struct_miqt_array"
}
@ -264,6 +271,18 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
rvalue = nameprefix + "_ms"
} else if p.ParameterType == "QByteArray" {
// Go: convert []byte -> miqt_string
// CABI: convert miqt_string -> QByteArray
// n.b. This can ALIAS the existing []byte data
gfs.imports["unsafe"] = struct{}{}
preamble += nameprefix + "_alias := C.struct_miqt_string{}\n"
preamble += nameprefix + "_alias.data = (*C.char)(unsafe.Pointer(&" + p.ParameterName + "[0]))\n"
preamble += nameprefix + "_alias.len = C.size_t(len(" + p.ParameterName + "))\n"
rvalue = nameprefix + "_alias"
} else if listType, ok := p.QListOf(); ok {
// QList<T>
// Go: convert T[] -> t* and len
@ -367,6 +386,19 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
afterword += assignExpr + namePrefix + "_ret"
return shouldReturn + " " + rvalue + "\n" + afterword
} else if rt.ParameterType == "QByteArray" {
// We receive the CABI type of a miqt_string. Convert it into []byte
// We must free the miqt_string data pointer - this is a data copy,
// not an alias
gfs.imports["unsafe"] = struct{}{}
shouldReturn = "var " + namePrefix + "_bytearray C.struct_miqt_string = "
afterword += namePrefix + "_ret := C.GoBytes(unsafe.Pointer(" + namePrefix + "_bytearray.data), C.int(int64(" + namePrefix + "_bytearray.len)))\n"
afterword += "C.free(unsafe.Pointer(" + namePrefix + "_bytearray.data))\n"
afterword += assignExpr + namePrefix + "_ret"
return shouldReturn + " " + rvalue + "\n" + afterword
} else if t, ok := rt.QListOf(); ok {
gfs.imports["unsafe"] = struct{}{}
@ -645,7 +677,7 @@ import "C"
if returnTypeDecl == "void" {
returnTypeDecl = ""
}
if m.ReturnType.QtClassType() && m.ReturnType.ParameterType != "QString" && !(m.ReturnType.Pointer || m.ReturnType.ByRef) {
if m.ReturnType.QtClassType() && m.ReturnType.ParameterType != "QString" && m.ReturnType.ParameterType != "QByteArray" && !(m.ReturnType.Pointer || m.ReturnType.ByRef) {
returnTypeDecl = "*" + returnTypeDecl
}

View File

@ -47,6 +47,7 @@ func AllowHeader(fullpath string) bool {
"qmaccocoaviewcontainer_mac.h", // Needs NSView* headers. TODO allow with darwin build tag
"qmacnativewidget_mac.h", // Needs NSView* headers. TODO allow with darwin build tag
"qstring.h", // QString does not exist in this binding
"qbytearray.h", // QByteArray does not exist in this binding
"qlist.h", // QList does not exist in this binding
"qvector.h": // QVector does not exist in this binding
return false
@ -211,6 +212,13 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
return ErrTooComplex
}
// QBuffer can accept a raw pointer to an internal QByteArray, but that
// doesn't work when QByteArray is deleted
// QDataStream
if p.ParameterType == "QByteArray" && p.Pointer && !isReturnType {
return ErrTooComplex
}
if p.ParameterType == "QFormLayout::ItemRole" && p.Pointer && !isReturnType { // Out-parameters in QFormLayout
return ErrTooComplex
}

View File

@ -110,7 +110,7 @@ func (p CppParameter) QtClassType() bool {
return true
}
if p.ParameterType == "QString" {
if p.ParameterType == "QString" || p.ParameterType == "QByteArray" {
return true
}