mirror of
https://github.com/mappu/miqt.git
synced 2025-03-11 18:10:22 +00:00
genbindings: add QPair<> support
This commit is contained in:
parent
dc39b7ca65
commit
58ec6e1821
@ -226,9 +226,6 @@ func AllowMethod(className string, mm CppMethod) error {
|
|||||||
// Any type not permitted by AllowClass is also not permitted by this method.
|
// Any type not permitted by AllowClass is also not permitted by this method.
|
||||||
func AllowType(p CppParameter, isReturnType bool) error {
|
func AllowType(p CppParameter, isReturnType bool) error {
|
||||||
|
|
||||||
if p.QPairOf() {
|
|
||||||
return ErrTooComplex // e.g. QGradientStop
|
|
||||||
}
|
|
||||||
if t, ok := p.QSetOf(); ok {
|
if t, ok := p.QSetOf(); ok {
|
||||||
if err := AllowType(t, isReturnType); err != nil {
|
if err := AllowType(t, isReturnType); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -258,6 +255,14 @@ func AllowType(p CppParameter, isReturnType bool) error {
|
|||||||
return ErrTooComplex
|
return ErrTooComplex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if kType, vType, ok := p.QPairOf(); ok {
|
||||||
|
if err := AllowType(kType, isReturnType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := AllowType(vType, isReturnType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if p.QMultiMapOf() {
|
if p.QMultiMapOf() {
|
||||||
return ErrTooComplex // e.g. Qt5 QNetwork qsslcertificate.h has a QMultiMap<QSsl::AlternativeNameEntryType, QString>
|
return ErrTooComplex // e.g. Qt5 QNetwork qsslcertificate.h has a QMultiMap<QSsl::AlternativeNameEntryType, QString>
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ func (p CppParameter) RenderTypeCabi() string {
|
|||||||
} else if _, _, ok := p.QMapOf(); ok {
|
} else if _, _, ok := p.QMapOf(); ok {
|
||||||
return "struct miqt_map"
|
return "struct miqt_map"
|
||||||
|
|
||||||
|
} else if _, _, ok := p.QPairOf(); ok {
|
||||||
|
return "struct miqt_map"
|
||||||
|
|
||||||
} else if (p.Pointer || p.ByRef) && p.QtClassType() {
|
} else if (p.Pointer || p.ByRef) && p.QtClassType() {
|
||||||
return cabiClassName(p.ParameterType) + "*"
|
return cabiClassName(p.ParameterType) + "*"
|
||||||
|
|
||||||
@ -267,6 +270,25 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
|
|||||||
preamble += indent + "}\n"
|
preamble += indent + "}\n"
|
||||||
return preamble, nameprefix + "_QMap"
|
return preamble, nameprefix + "_QMap"
|
||||||
|
|
||||||
|
} 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"
|
||||||
|
|
||||||
|
kType.ParameterName = nameprefix + "_first_arr[0]"
|
||||||
|
addPreK, addFwdK := emitCABI2CppForwarding(kType, indent+"\t")
|
||||||
|
preamble += addPreK
|
||||||
|
|
||||||
|
vType.ParameterName = nameprefix + "_second_arr[0]"
|
||||||
|
addPreV, addFwdV := emitCABI2CppForwarding(vType, indent+"\t")
|
||||||
|
preamble += addPreV
|
||||||
|
|
||||||
|
preamble += indent + nameprefix + "_QPair.first = " + addFwdK + ";\n"
|
||||||
|
preamble += indent + nameprefix + "_QPair.second = " + addFwdV + ";\n"
|
||||||
|
|
||||||
|
return preamble, nameprefix + "_QPair"
|
||||||
|
|
||||||
} else if p.IsFlagType() || p.IntType() || p.IsKnownEnum() {
|
} else if p.IsFlagType() || p.IntType() || p.IsKnownEnum() {
|
||||||
castSrc := p.ParameterName
|
castSrc := p.ParameterName
|
||||||
castType := p.RenderTypeQtCpp()
|
castType := p.RenderTypeQtCpp()
|
||||||
@ -452,6 +474,26 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
|
|||||||
afterCall += indent + assignExpression + "" + namePrefix + "_out;\n"
|
afterCall += indent + assignExpression + "" + namePrefix + "_out;\n"
|
||||||
return indent + shouldReturn + rvalue + ";\n" + afterCall
|
return indent + shouldReturn + rvalue + ";\n" + afterCall
|
||||||
|
|
||||||
|
} else if kType, vType, ok := p.QPairOf(); ok {
|
||||||
|
// QPair<T1,T2>
|
||||||
|
|
||||||
|
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
|
||||||
|
|
||||||
|
afterCall += indent + "// Convert QPair<> from C++ memory to manually-managed C memory\n"
|
||||||
|
afterCall += indent + "" + kType.RenderTypeCabi() + "* " + namePrefix + "_first_arr = static_cast<" + kType.RenderTypeCabi() + "*>(malloc(sizeof(" + kType.RenderTypeCabi() + ")));\n"
|
||||||
|
afterCall += indent + "" + vType.RenderTypeCabi() + "* " + namePrefix + "_second_arr = static_cast<" + vType.RenderTypeCabi() + "*>(malloc(sizeof(" + vType.RenderTypeCabi() + ")));\n"
|
||||||
|
|
||||||
|
afterCall += emitAssignCppToCabi(indent+namePrefix+"_first_arr[0] = ", kType, namePrefix+"_ret.first")
|
||||||
|
afterCall += emitAssignCppToCabi(indent+namePrefix+"_second_arr[0] = ", vType, namePrefix+"_ret.second")
|
||||||
|
|
||||||
|
afterCall += indent + "struct miqt_map " + namePrefix + "_out;\n"
|
||||||
|
afterCall += indent + "" + namePrefix + "_out.len = 1;\n"
|
||||||
|
afterCall += indent + "" + namePrefix + "_out.keys = static_cast<void*>(" + namePrefix + "_first_arr);\n"
|
||||||
|
afterCall += indent + "" + namePrefix + "_out.values = static_cast<void*>(" + namePrefix + "_second_arr);\n"
|
||||||
|
|
||||||
|
afterCall += indent + assignExpression + "" + namePrefix + "_out;\n"
|
||||||
|
return indent + shouldReturn + rvalue + ";\n" + afterCall
|
||||||
|
|
||||||
} else if p.QtClassType() && p.ByRef {
|
} else if p.QtClassType() && p.ByRef {
|
||||||
// It's a pointer in disguise, just needs one cast
|
// It's a pointer in disguise, just needs one cast
|
||||||
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
|
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
|
||||||
|
@ -43,6 +43,12 @@ func (p CppParameter) RenderTypeGo(gfs *goFileState) string {
|
|||||||
return "map[" + t1.RenderTypeGo(gfs) + "]" + t2.RenderTypeGo(gfs)
|
return "map[" + t1.RenderTypeGo(gfs) + "]" + t2.RenderTypeGo(gfs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t1, t2, ok := p.QPairOf(); ok {
|
||||||
|
// Design QPair using capital-named members, in case it gets passed
|
||||||
|
// across packages
|
||||||
|
return "struct { First " + t1.RenderTypeGo(gfs) + " ; Second " + t2.RenderTypeGo(gfs) + " }"
|
||||||
|
}
|
||||||
|
|
||||||
if p.ParameterType == "void" && p.Pointer {
|
if p.ParameterType == "void" && p.Pointer {
|
||||||
return "unsafe.Pointer"
|
return "unsafe.Pointer"
|
||||||
}
|
}
|
||||||
@ -169,6 +175,10 @@ func (p CppParameter) parameterTypeCgo() string {
|
|||||||
return "C.struct_miqt_map"
|
return "C.struct_miqt_map"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, _, ok := p.QPairOf(); ok {
|
||||||
|
return "C.struct_miqt_map"
|
||||||
|
}
|
||||||
|
|
||||||
// Cgo internally binds void* as unsafe.Pointer{}
|
// Cgo internally binds void* as unsafe.Pointer{}
|
||||||
if p.ParameterType == "void" && p.Pointer {
|
if p.ParameterType == "void" && p.Pointer {
|
||||||
return "unsafe.Pointer"
|
return "unsafe.Pointer"
|
||||||
@ -366,6 +376,30 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
|
|||||||
|
|
||||||
rvalue = nameprefix + "_mm"
|
rvalue = nameprefix + "_mm"
|
||||||
|
|
||||||
|
} else if kType, vType, ok := p.QPairOf(); ok {
|
||||||
|
// QPair<T>
|
||||||
|
|
||||||
|
gfs.imports["unsafe"] = struct{}{}
|
||||||
|
|
||||||
|
preamble += nameprefix + "_First_CArray := (*[0xffff]" + kType.parameterTypeCgo() + ")(C.malloc(C.size_t(" + kType.mallocSizeCgoExpression() + ")))\n"
|
||||||
|
preamble += "defer C.free(unsafe.Pointer(" + nameprefix + "_First_CArray))\n"
|
||||||
|
|
||||||
|
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"
|
||||||
|
addPreamble, innerRvalue := gfs.emitParameterGo2CABIForwarding(kType)
|
||||||
|
preamble += addPreamble
|
||||||
|
preamble += nameprefix + "_First_CArray[0] = " + innerRvalue + "\n"
|
||||||
|
|
||||||
|
vType.ParameterName = p.ParameterName + ".Second"
|
||||||
|
addPreamble, innerRvalue = gfs.emitParameterGo2CABIForwarding(vType)
|
||||||
|
preamble += addPreamble
|
||||||
|
preamble += nameprefix + "_Second_CArray[0] = " + innerRvalue + "\n"
|
||||||
|
|
||||||
|
preamble += nameprefix + "_pair := C.struct_miqt_map{\nlen: 1,\nkeys: unsafe.Pointer(" + nameprefix + "_First_CArray),\nvalues: unsafe.Pointer(" + nameprefix + "_Second_CArray),\n}\n"
|
||||||
|
|
||||||
|
rvalue = nameprefix + "_pair"
|
||||||
|
|
||||||
} else if p.Pointer && p.ParameterType == "char" {
|
} else if p.Pointer && p.ParameterType == "char" {
|
||||||
// Single char* argument
|
// Single char* argument
|
||||||
@ -506,6 +540,20 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
|
|||||||
afterword += assignExpr + " " + namePrefix + "_ret\n"
|
afterword += assignExpr + " " + namePrefix + "_ret\n"
|
||||||
return shouldReturn + " " + rvalue + "\n" + afterword
|
return shouldReturn + " " + rvalue + "\n" + afterword
|
||||||
|
|
||||||
|
} else if kType, vType, ok := rt.QPairOf(); ok {
|
||||||
|
gfs.imports["unsafe"] = struct{}{}
|
||||||
|
|
||||||
|
shouldReturn = "var " + namePrefix + "_mm C.struct_miqt_map = "
|
||||||
|
|
||||||
|
afterword += namePrefix + "_First_CArray := (*[0xffff]" + kType.parameterTypeCgo() + ")(unsafe.Pointer(" + namePrefix + "_mm.keys))\n"
|
||||||
|
afterword += namePrefix + "_Second_CArray := (*[0xffff]" + vType.parameterTypeCgo() + ")(unsafe.Pointer(" + namePrefix + "_mm.values))\n"
|
||||||
|
|
||||||
|
afterword += gfs.emitCabiToGo(namePrefix+"_entry_First := ", kType, namePrefix+"_First_CArray[0]") + "\n"
|
||||||
|
afterword += gfs.emitCabiToGo(namePrefix+"_entry_Second := ", vType, namePrefix+"_Second_CArray[0]") + "\n"
|
||||||
|
|
||||||
|
afterword += assignExpr + " " + rt.RenderTypeGo(gfs) + " { First: " + namePrefix + "_entry_First , Second: " + namePrefix + "_entry_Second }\n"
|
||||||
|
return shouldReturn + " " + rvalue + "\n" + afterword
|
||||||
|
|
||||||
} else if rt.QtClassType() {
|
} else if rt.QtClassType() {
|
||||||
// Construct our Go type based on this inner CABI type
|
// Construct our Go type based on this inner CABI type
|
||||||
shouldReturn = "" + namePrefix + "_ret := "
|
shouldReturn = "" + namePrefix + "_ret := "
|
||||||
|
@ -151,8 +151,21 @@ func (p CppParameter) QMapOf() (CppParameter, CppParameter, bool) {
|
|||||||
return CppParameter{}, CppParameter{}, false
|
return CppParameter{}, CppParameter{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p CppParameter) QPairOf() bool {
|
func (p CppParameter) QPairOf() (CppParameter, CppParameter, bool) {
|
||||||
return strings.HasPrefix(p.ParameterType, `QPair<`) // TODO support this
|
if strings.HasPrefix(p.ParameterType, `QPair<`) && strings.HasSuffix(p.ParameterType, `>`) {
|
||||||
|
interior := tokenizeMultipleParameters(p.ParameterType[6 : len(p.ParameterType)-1])
|
||||||
|
if len(interior) != 2 {
|
||||||
|
panic("QPair<> has unexpected number of template arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
first := parseSingleTypeString(interior[0])
|
||||||
|
first.ParameterName = p.ParameterName + "_first"
|
||||||
|
second := parseSingleTypeString(interior[1])
|
||||||
|
second.ParameterName = p.ParameterName + "_second"
|
||||||
|
return first, second, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return CppParameter{}, CppParameter{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p CppParameter) QSetOf() (CppParameter, bool) {
|
func (p CppParameter) QSetOf() (CppParameter, bool) {
|
||||||
|
@ -44,6 +44,20 @@ func applyTypedefs(p CppParameter) CppParameter {
|
|||||||
p.QtCppOriginalType = &tmp
|
p.QtCppOriginalType = &tmp
|
||||||
}
|
}
|
||||||
p.ParameterType = p.ParameterType[0:bpos] + `<` + kType2.RenderTypeQtCpp() + `, ` + vType2.RenderTypeQtCpp() + `>`
|
p.ParameterType = p.ParameterType[0:bpos] + `<` + kType2.RenderTypeQtCpp() + `, ` + vType2.RenderTypeQtCpp() + `>`
|
||||||
|
|
||||||
|
} else if kType, vType, ok := p.QPairOf(); ok {
|
||||||
|
kType2 := applyTypedefs(kType)
|
||||||
|
kType2.QtCppOriginalType = nil
|
||||||
|
|
||||||
|
vType2 := applyTypedefs(vType)
|
||||||
|
vType2.QtCppOriginalType = nil
|
||||||
|
|
||||||
|
if p.QtCppOriginalType == nil {
|
||||||
|
tmp := p // copy
|
||||||
|
p.QtCppOriginalType = &tmp
|
||||||
|
}
|
||||||
|
p.ParameterType = `QPair<` + kType2.RenderTypeQtCpp() + `, ` + vType2.RenderTypeQtCpp() + `>`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
|
Loading…
x
Reference in New Issue
Block a user