genbindings: remember precise QList/QMap container types

This commit is contained in:
mappu 2025-04-11 22:32:22 +12:00
parent 79024a373f
commit 5af3cc6dfe
5 changed files with 35 additions and 45 deletions

View File

@ -413,7 +413,7 @@ func AllowType(p CppParameter, isReturnType bool) error {
return err
}
}
if t, ok := p.QListOf(); ok {
if t, _, ok := p.QListOf(); ok {
if err := AllowType(t, isReturnType); err != nil { // e.g. QGradientStops is a QVector<> (OK) of QGradientStop (not OK)
return err
}
@ -424,7 +424,7 @@ func AllowType(p CppParameter, isReturnType bool) error {
return ErrTooComplex
}
}
if kType, vType, ok := p.QMapOf(); ok {
if kType, vType, _, ok := p.QMapOf(); ok {
if err := AllowType(kType, isReturnType); err != nil {
return err
}

View File

@ -82,13 +82,13 @@ func (p CppParameter) RenderTypeCabi() string {
} else if p.ParameterType == "QByteArray" {
return "struct miqt_string"
} else if inner, ok := p.QListOf(); ok {
} else if inner, _, ok := p.QListOf(); ok {
return "struct miqt_array " + cppComment("of "+inner.RenderTypeCabi())
} else if inner, ok := p.QSetOf(); ok {
return "struct miqt_array " + cppComment("set of "+inner.RenderTypeCabi())
} else if inner1, inner2, ok := p.QMapOf(); ok {
} else if inner1, inner2, _, ok := p.QMapOf(); ok {
return "struct miqt_map " + cppComment("of "+inner1.RenderTypeCabi()+" to "+inner2.RenderTypeCabi())
} else if inner1, inner2, ok := p.QPairOf(); ok {
@ -274,7 +274,7 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
preamble += indent + "QByteArray " + nameprefix + "_QByteArray(" + p.cParameterName() + ".data, " + p.cParameterName() + ".len);\n"
return preamble, nameprefix + "_QByteArray"
} else if listType, ok := p.QListOf(); ok {
} else if listType, _, ok := p.QListOf(); ok {
preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QList;\n"
preamble += indent + nameprefix + "_QList.reserve(" + p.cParameterName() + ".len);\n"
@ -296,12 +296,12 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
return preamble, nameprefix + "_QList"
}
} else if kType, vType, ok := p.QMapOf(); ok {
} else if kType, vType, mapContainerType, ok := p.QMapOf(); ok {
preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QMap;\n"
// This container may be a QMap or a QHash
// QHash supports .reserve(), but QMap doesn't
if strings.HasPrefix(p.ParameterType, "QHash<") {
if mapContainerType == "QHash" {
preamble += indent + nameprefix + "_QMap.reserve(" + p.cParameterName() + ".len);\n"
}
@ -461,7 +461,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
afterCall += indent + assignExpression + namePrefix + "_ms;\n"
return indent + shouldReturn + rvalue + ";\n" + afterCall
} else if t, ok := p.QListOf(); ok {
} else if t, _, ok := p.QListOf(); ok {
// In some cases rvalue is a function call and the temporary
// is necessary; in some cases it's a literal and the temporary is
@ -503,7 +503,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
afterCall += indent + assignExpression + "" + namePrefix + "_out;\n"
return indent + shouldReturn + rvalue + ";\n" + afterCall
} else if kType, vType, ok := p.QMapOf(); ok {
} else if kType, vType, _, ok := p.QMapOf(); ok {
// QMap<K,V>
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
@ -635,13 +635,13 @@ func getCabiZeroValue(p CppParameter) string {
} else if p.ParameterType == "QString" || p.ParameterType == "QByteArray" {
return "(struct miqt_string){}"
} else if _, ok := p.QListOf(); ok {
} else if _, _, ok := p.QListOf(); ok {
return "(struct miqt_array){}"
} else if _, ok := p.QSetOf(); ok {
return "(struct miqt_array){}"
} else if _, _, ok := p.QMapOf(); ok {
} else if _, _, _, ok := p.QMapOf(); ok {
return "(struct miqt_map){}"
} else if _, _, ok := p.QPairOf(); ok {
@ -666,12 +666,12 @@ func getReferencedTypes(src *CppParsedHeader) []string {
if p.QtClassType() {
foundTypes[p.ParameterType] = struct{}{}
}
if t, ok := p.QListOf(); ok {
foundTypes["QList"] = struct{}{} // FIXME or QVector?
if t, containerType, ok := p.QListOf(); ok {
foundTypes[containerType] = struct{}{} // QList / QVector
maybeAddType(t)
}
if kType, vType, ok := p.QMapOf(); ok {
foundTypes["QMap"] = struct{}{} // FIXME or QHash?
if kType, vType, containerType, ok := p.QMapOf(); ok {
foundTypes[containerType] = struct{}{} // QMap / QHash
maybeAddType(kType)
maybeAddType(vType)
}

View File

@ -50,7 +50,7 @@ func (p CppParameter) RenderTypeGo(gfs *goFileState) string {
return "[]byte"
}
if t, ok := p.QListOf(); ok {
if t, _, ok := p.QListOf(); ok {
return "[]" + t.RenderTypeGo(gfs)
}
@ -58,7 +58,7 @@ func (p CppParameter) RenderTypeGo(gfs *goFileState) string {
return "map[" + t.RenderTypeGo(gfs) + "]struct{}"
}
if t1, t2, ok := p.QMapOf(); ok {
if t1, t2, _, ok := p.QMapOf(); ok {
return "map[" + t1.RenderTypeGo(gfs) + "]" + t2.RenderTypeGo(gfs)
}
@ -196,7 +196,7 @@ func (p CppParameter) parameterTypeCgo() string {
return "C.struct_miqt_string"
}
if _, ok := p.QListOf(); ok {
if _, _, ok := p.QListOf(); ok {
return "C.struct_miqt_array"
}
@ -204,7 +204,7 @@ func (p CppParameter) parameterTypeCgo() string {
return "C.struct_miqt_array"
}
if _, _, ok := p.QMapOf(); ok {
if _, _, _, ok := p.QMapOf(); ok {
return "C.struct_miqt_map"
}
@ -359,7 +359,7 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
rvalue = nameprefix + "_alias"
} else if listType, ok := p.QListOf(); ok {
} else if listType, _, ok := p.QListOf(); ok {
// QList<T>
// Go: convert T[] -> t* and len
// CABI: create a real QList<>
@ -386,7 +386,7 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
} else if _, ok := p.QSetOf(); ok {
panic("QSet<> arguments are not yet implemented") // n.b. doesn't seem to exist in QtCore/QtGui/QtWidgets at all
} else if kType, vType, ok := p.QMapOf(); ok {
} else if kType, vType, _, ok := p.QMapOf(); ok {
// QMap<T>
gfs.imports["unsafe"] = struct{}{}
@ -532,7 +532,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
afterword += assignExpr + namePrefix + "_ret"
return shouldReturn + " " + rvalue + "\n" + afterword
} else if t, ok := rt.QListOf(); ok {
} else if t, _, ok := rt.QListOf(); ok {
gfs.imports["unsafe"] = struct{}{}
shouldReturn = "var " + namePrefix + "_ma C.struct_miqt_array = "
@ -565,7 +565,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
afterword += assignExpr + " " + namePrefix + "_ret\n"
return shouldReturn + " " + rvalue + "\n" + afterword
} else if kType, vType, ok := rt.QMapOf(); ok {
} else if kType, vType, _, ok := rt.QMapOf(); ok {
gfs.imports["unsafe"] = struct{}{}
shouldReturn = "var " + namePrefix + "_mm C.struct_miqt_map = "

View File

@ -112,23 +112,23 @@ func (p CppParameter) IsKnownEnum() bool {
return ok
}
func (p CppParameter) QListOf() (CppParameter, bool) {
func (p CppParameter) QListOf() (CppParameter, string, bool) {
if strings.HasPrefix(p.ParameterType, "QList<") && strings.HasSuffix(p.ParameterType, `>`) {
ret := parseSingleTypeString(p.ParameterType[6 : len(p.ParameterType)-1])
ret.ParameterName = p.ParameterName + "_lv"
return ret, true
return ret, "QList", true
}
if strings.HasPrefix(p.ParameterType, "QVector<") && strings.HasSuffix(p.ParameterType, `>`) {
ret := parseSingleTypeString(p.ParameterType[8 : len(p.ParameterType)-1])
ret.ParameterName = p.ParameterName + "_vv"
return ret, true
return ret, "QVector", true
}
return CppParameter{}, false
return CppParameter{}, "", false
}
func (p CppParameter) QMapOf() (CppParameter, CppParameter, bool) {
func (p CppParameter) QMapOf() (CppParameter, CppParameter, string, bool) {
// n.b. Need to block QMap<k,v>::const_terator
if strings.HasPrefix(p.ParameterType, `QMap<`) && strings.HasSuffix(p.ParameterType, `>`) {
@ -141,7 +141,7 @@ func (p CppParameter) QMapOf() (CppParameter, CppParameter, bool) {
first.ParameterName = p.ParameterName + "_mapkey"
second := parseSingleTypeString(interior[1])
second.ParameterName = p.ParameterName + "_mapval"
return first, second, true
return first, second, "QMap", true
}
if strings.HasPrefix(p.ParameterType, `QHash<`) && strings.HasSuffix(p.ParameterType, `>`) {
@ -154,10 +154,10 @@ func (p CppParameter) QMapOf() (CppParameter, CppParameter, bool) {
first.ParameterName = p.ParameterName + "_hashkey"
second := parseSingleTypeString(interior[1])
second.ParameterName = p.ParameterName + "_hashval"
return first, second, true
return first, second, "QHash", true
}
return CppParameter{}, CppParameter{}, false
return CppParameter{}, CppParameter{}, "", false
}
func (p CppParameter) QPairOf() (CppParameter, CppParameter, bool) {

View File

@ -1,9 +1,5 @@
package main
import (
"strings"
)
func applyTypedefs(p CppParameter) CppParameter {
for {
@ -14,36 +10,30 @@ func applyTypedefs(p CppParameter) CppParameter {
p.ApplyTypedef(td.Typedef.UnderlyingType)
}
if t, ok := p.QListOf(); ok {
if t, containerType, ok := p.QListOf(); ok {
t2 := applyTypedefs(t) // recursive
// Wipe out so that RenderTypeQtCpp() does not see it
t2.QtCppOriginalType = nil
// QListOf returns for either QList< or QVector<
// Patch it up to the first < position and last character
bpos := strings.Index(p.ParameterType, `<`)
if p.QtCppOriginalType == nil {
tmp := p // copy
p.QtCppOriginalType = &tmp
}
p.ParameterType = p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>`
p.ParameterType = containerType + `<` + t2.RenderTypeQtCpp() + `>`
} else if kType, vType, ok := p.QMapOf(); ok {
} else if kType, vType, containerType, ok := p.QMapOf(); ok {
kType2 := applyTypedefs(kType)
kType2.QtCppOriginalType = nil
vType2 := applyTypedefs(vType)
vType2.QtCppOriginalType = nil
bpos := strings.Index(p.ParameterType, `<`)
if p.QtCppOriginalType == nil {
tmp := p // copy
p.QtCppOriginalType = &tmp
}
p.ParameterType = p.ParameterType[0:bpos] + `<` + kType2.RenderTypeQtCpp() + `, ` + vType2.RenderTypeQtCpp() + `>`
p.ParameterType = containerType + `<` + kType2.RenderTypeQtCpp() + `, ` + vType2.RenderTypeQtCpp() + `>`
} else if kType, vType, ok := p.QPairOf(); ok {
kType2 := applyTypedefs(kType)