genbindings: initial QSet<> support

This commit is contained in:
mappu 2024-09-17 21:48:26 +12:00
parent fc33475f3c
commit 25008355a7
7 changed files with 89 additions and 6 deletions

View File

@ -145,6 +145,9 @@ func emitParametersCabi(m CppMethod, selfType string) string {
} else if t, ok := p.QListOf(); ok {
tmp = append(tmp, "struct miqt_array* /* of "+t.RenderTypeCabi()+" */ "+p.ParameterName)
} else if t, ok := p.QSetOf(); ok {
tmp = append(tmp, "struct miqt_array* /* Set of "+t.RenderTypeCabi()+" */ "+p.ParameterName)
} else if p.QtClassType() {
if p.ByRef || p.Pointer {
@ -232,6 +235,9 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
return preamble, "static_cast<" + castType + ">(" + castSrc + ")"
}
} 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 p.ByRef {
if p.Pointer {
// By ref and by pointer
@ -319,8 +325,22 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
afterCall += indent + assignExpression + "" + namePrefix + "_out;\n"
} else if _, ok := p.QSetOf(); ok {
// ...
} else if t, ok := p.QSetOf(); ok {
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
afterCall += indent + "// Convert QList<> from C++ memory to manually-managed C memory\n"
afterCall += indent + "" + t.RenderTypeCabi() + "* " + namePrefix + "_arr = static_cast<" + t.RenderTypeCabi() + "*>(malloc(sizeof(" + t.RenderTypeCabi() + ") * " + namePrefix + "_ret.length()));\n"
afterCall += indent + "int " + namePrefix + "_ctr = 0;\n"
afterCall += indent + "for (const auto " + namePrefix + "_elem& : " + rvalue + " ) {\n"
afterCall += emitAssignCppToCabi(indent+"\t"+namePrefix+"_arr["+namePrefix+"_ctr++] = ", t, namePrefix+"_elem")
afterCall += indent + "}\n"
afterCall += indent + "struct miqt_array* " + namePrefix + "_out = static_cast<struct miqt_array*>(malloc(sizeof(struct miqt_array)));\n"
afterCall += indent + "" + namePrefix + "_out->len = " + namePrefix + "_ret.length();\n"
afterCall += indent + "" + namePrefix + "_out->data = static_cast<void*>(" + namePrefix + "_arr);\n"
afterCall += indent + assignExpression + "" + namePrefix + "_out;\n"
} else if p.QtClassType() && p.ByRef {
// It's a pointer in disguise, just needs one cast

View File

@ -31,6 +31,10 @@ func (p CppParameter) RenderTypeGo() string {
return "[]" + t.RenderTypeGo()
}
if t, ok := p.QSetOf(); ok {
return "map[" + t.RenderTypeGo() + "]struct{}"
}
ret := ""
if p.ByRef || p.Pointer {
ret += "*"
@ -114,6 +118,10 @@ func (p CppParameter) parameterTypeCgo() string {
return "*C.struct_miqt_array"
}
if _, ok := p.QSetOf(); ok {
return "*C.struct_miqt_array"
}
tmp := strings.Replace(p.RenderTypeCabi(), `*`, "", -1)
if strings.HasPrefix(tmp, "const ") {
tmp = tmp[6:] // Constness doesn't survive the CABI boundary
@ -245,6 +253,9 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
rvalue = p.ParameterName + "_ma"
} 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 p.Pointer && p.ParameterType == "char" {
// Single char* argument
gfs.imports["unsafe"] = struct{}{}
@ -317,6 +328,23 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
afterword += "C.free(unsafe.Pointer(" + namePrefix + "_ma))\n"
afterword += assignExpr + " " + namePrefix + "_ret\n"
} else if t, ok := rt.QSetOf(); ok {
gfs.imports["unsafe"] = struct{}{}
shouldReturn = "var " + namePrefix + "_ma *C.struct_miqt_array = "
afterword += namePrefix + "_ret := make(map[" + t.RenderTypeGo() + "]struct{}, int(" + namePrefix + "_ma.len))\n"
afterword += namePrefix + "_outCast := (*[0xffff]" + t.parameterTypeCgo() + ")(unsafe.Pointer(" + namePrefix + "_ma.data)) // hey ya\n"
afterword += "for i := 0; i < int(" + namePrefix + "_ma.len); i++ {\n"
afterword += gfs.emitCabiToGo(namePrefix+"_element := ", t, namePrefix+"_outCast[i]") + "\n"
afterword += namePrefix + "_ret[" + namePrefix + "_element] = struct{}{}\n"
afterword += "}\n"
afterword += "C.free(unsafe.Pointer(" + namePrefix + "_ma))\n"
afterword += assignExpr + " " + namePrefix + "_ret\n"
} else if rt.QtClassType() {
// Construct our Go type based on this inner CABI type
shouldReturn = "" + namePrefix + "_ret := "

View File

@ -90,8 +90,10 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
if p.QPairOf() {
return ErrTooComplex // e.g. QGradientStop
}
if p.QSetOf() {
return ErrTooComplex // e.g. QStateMachine
if t, ok := p.QSetOf(); ok {
if err := CheckComplexity(t, isReturnType); err != nil {
return err
}
}
if t, ok := p.QListOf(); ok {
if err := CheckComplexity(t, isReturnType); err != nil { // e.g. QGradientStops is a QVector<> (OK) of QGradientStop (not OK)

View File

@ -156,8 +156,14 @@ func (p CppParameter) QPairOf() bool {
return strings.HasPrefix(p.ParameterType, `QPair<`) // TODO support this
}
func (p CppParameter) QSetOf() bool {
return strings.HasPrefix(p.ParameterType, `QSet<`) // TODO support this
func (p CppParameter) QSetOf() (CppParameter, bool) {
if strings.HasPrefix(p.ParameterType, `QSet<`) {
ret := parseSingleTypeString(p.ParameterType[5 : len(p.ParameterType)-1])
ret.ParameterName = p.ParameterName + "_sv"
return ret, true
}
return CppParameter{}, false
}
func (p CppParameter) IntType() bool {

View File

@ -126,6 +126,20 @@ bool QStateMachine_CancelDelayedEvent(QStateMachine* self, int id) {
return self->cancelDelayedEvent(static_cast<int>(id));
}
struct miqt_array* QStateMachine_Configuration(const QStateMachine* self) {
QSet<QAbstractState *> _ret = self->configuration();
// Convert QList<> from C++ memory to manually-managed C memory
QAbstractState** _arr = static_cast<QAbstractState**>(malloc(sizeof(QAbstractState*) * _ret.length()));
int _ctr = 0;
for (const auto _elem& : self->configuration() ) {
_arr[_ctr++] = _elem;
}
struct miqt_array* _out = static_cast<struct miqt_array*>(malloc(sizeof(struct miqt_array)));
_out->len = _ret.length();
_out->data = static_cast<void*>(_arr);
return _out;
}
bool QStateMachine_EventFilter(QStateMachine* self, QObject* watched, QEvent* event) {
return self->eventFilter(watched, event);
}

View File

@ -174,6 +174,18 @@ func (this *QStateMachine) CancelDelayedEvent(id int) bool {
return (bool)(C.QStateMachine_CancelDelayedEvent(this.h, (C.int)(id)))
}
func (this *QStateMachine) Configuration() map[*QAbstractState]struct{} {
var _ma *C.struct_miqt_array = C.QStateMachine_Configuration(this.h)
_ret := make(map[*QAbstractState]struct{}, int(_ma.len))
_outCast := (*[0xffff]*C.QAbstractState)(unsafe.Pointer(_ma.data)) // hey ya
for i := 0; i < int(_ma.len); i++ {
_element := newQAbstractState_U(unsafe.Pointer(_outCast[i]))
_ret[_element] = struct{}{}
}
C.free(unsafe.Pointer(_ma))
return _ret
}
func (this *QStateMachine) EventFilter(watched *QObject, event *QEvent) bool {
return (bool)(C.QStateMachine_EventFilter(this.h, watched.cPointer(), event.cPointer()))
}

View File

@ -64,6 +64,7 @@ void QStateMachine_SetGlobalRestorePolicy(QStateMachine* self, uintptr_t restore
void QStateMachine_PostEvent(QStateMachine* self, QEvent* event);
int QStateMachine_PostDelayedEvent(QStateMachine* self, QEvent* event, int delay);
bool QStateMachine_CancelDelayedEvent(QStateMachine* self, int id);
struct miqt_array* QStateMachine_Configuration(const QStateMachine* self);
bool QStateMachine_EventFilter(QStateMachine* self, QObject* watched, QEvent* event);
void QStateMachine_Start(QStateMachine* self);
void QStateMachine_Stop(QStateMachine* self);