Skip to content

Commit

Permalink
add support for haxe and swift + fix interop stack overflow issue
Browse files Browse the repository at this point in the history
* fix unsafe pointer arithmetic issues
  • Loading branch information
therecipe committed Jul 1, 2020
1 parent 66b6100 commit 7f61353
Show file tree
Hide file tree
Showing 43 changed files with 2,183 additions and 857 deletions.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Mfile*
*/cgo_*
*/minimal_*
*/*.d.ts
*/*.dart
*/*.hx
*/*.swift

interop/moc*

Expand All @@ -25,4 +28,6 @@ interop/moc*
/internal/examples/**/deploy
/internal/examples/**/moc*
/internal/examples/**/rcc*
/internal/examples/**/uic*
/internal/examples/**/uic*

flutter/*lutter*
12 changes: 6 additions & 6 deletions core/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14092,14 +14092,14 @@ char QMetaType_QMetaType_Compare(void* lhs, void* rhs, int typeId, int result)
return QMetaType::compare(lhs, rhs, typeId, &result);
}

void* QMetaType_QMetaType_Construct2(int ty, void* where, void* copy)
void* QMetaType_QMetaType_Construct2(int ty, void* whe, void* copy)
{
return QMetaType::construct(ty, where, copy);
return QMetaType::construct(ty, whe, copy);
}

void* QMetaType_Construct3(void* ptr, void* where, void* copy)
void* QMetaType_Construct3(void* ptr, void* whe, void* copy)
{
return static_cast<QMetaType*>(ptr)->construct(where, copy);
return static_cast<QMetaType*>(ptr)->construct(whe, copy);
}

char QMetaType_QMetaType_Convert(void* from, int fromTypeId, void* to, int toTypeId)
Expand Down Expand Up @@ -14132,9 +14132,9 @@ void QMetaType_Destroy2(void* ptr, void* data)
static_cast<QMetaType*>(ptr)->destroy(data);
}

void QMetaType_QMetaType_Destruct(int ty, void* where)
void QMetaType_QMetaType_Destruct(int ty, void* whe)
{
QMetaType::destruct(ty, where);
QMetaType::destruct(ty, whe);
}

void QMetaType_Destruct2(void* ptr, void* data)
Expand Down
20 changes: 10 additions & 10 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -32066,17 +32066,17 @@ func (ptr *QMetaType) Compare(lhs unsafe.Pointer, rhs unsafe.Pointer, typeId int
return int8(C.QMetaType_QMetaType_Compare(lhs, rhs, C.int(int32(typeId)), C.int(int32(result)))) != 0
}

func QMetaType_Construct2(ty int, where unsafe.Pointer, copy unsafe.Pointer) unsafe.Pointer {
return C.QMetaType_QMetaType_Construct2(C.int(int32(ty)), where, copy)
func QMetaType_Construct2(ty int, whe unsafe.Pointer, copy unsafe.Pointer) unsafe.Pointer {
return C.QMetaType_QMetaType_Construct2(C.int(int32(ty)), whe, copy)
}

func (ptr *QMetaType) Construct2(ty int, where unsafe.Pointer, copy unsafe.Pointer) unsafe.Pointer {
return C.QMetaType_QMetaType_Construct2(C.int(int32(ty)), where, copy)
func (ptr *QMetaType) Construct2(ty int, whe unsafe.Pointer, copy unsafe.Pointer) unsafe.Pointer {
return C.QMetaType_QMetaType_Construct2(C.int(int32(ty)), whe, copy)
}

func (ptr *QMetaType) Construct3(where unsafe.Pointer, copy unsafe.Pointer) unsafe.Pointer {
func (ptr *QMetaType) Construct3(whe unsafe.Pointer, copy unsafe.Pointer) unsafe.Pointer {
if ptr.Pointer() != nil {
return C.QMetaType_Construct3(ptr.Pointer(), where, copy)
return C.QMetaType_Construct3(ptr.Pointer(), whe, copy)
}
return nil
}
Expand Down Expand Up @@ -32126,12 +32126,12 @@ func (ptr *QMetaType) Destroy2(data unsafe.Pointer) {
}
}

func QMetaType_Destruct(ty int, where unsafe.Pointer) {
C.QMetaType_QMetaType_Destruct(C.int(int32(ty)), where)
func QMetaType_Destruct(ty int, whe unsafe.Pointer) {
C.QMetaType_QMetaType_Destruct(C.int(int32(ty)), whe)
}

func (ptr *QMetaType) Destruct(ty int, where unsafe.Pointer) {
C.QMetaType_QMetaType_Destruct(C.int(int32(ty)), where)
func (ptr *QMetaType) Destruct(ty int, whe unsafe.Pointer) {
C.QMetaType_QMetaType_Destruct(C.int(int32(ty)), whe)
}

func (ptr *QMetaType) Destruct2(data unsafe.Pointer) {
Expand Down
6 changes: 3 additions & 3 deletions core/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -2178,15 +2178,15 @@ char QMetaProperty_Write(void* ptr, void* object, void* value);
char QMetaProperty_WriteOnGadget(void* ptr, void* gadget, void* value);
void* QMetaType_NewQMetaType(int typeId);
char QMetaType_QMetaType_Compare(void* lhs, void* rhs, int typeId, int result);
void* QMetaType_QMetaType_Construct2(int ty, void* where, void* copy);
void* QMetaType_Construct3(void* ptr, void* where, void* copy);
void* QMetaType_QMetaType_Construct2(int ty, void* whe, void* copy);
void* QMetaType_Construct3(void* ptr, void* whe, void* copy);
char QMetaType_QMetaType_Convert(void* from, int fromTypeId, void* to, int toTypeId);
void* QMetaType_QMetaType_Create(int ty, void* copy);
void* QMetaType_Create2(void* ptr, void* copy);
char QMetaType_QMetaType_DebugStream(void* dbg, void* rhs, int typeId);
void QMetaType_QMetaType_Destroy(int ty, void* data);
void QMetaType_Destroy2(void* ptr, void* data);
void QMetaType_QMetaType_Destruct(int ty, void* where);
void QMetaType_QMetaType_Destruct(int ty, void* whe);
void QMetaType_Destruct2(void* ptr, void* data);
char QMetaType_QMetaType_Equals(void* lhs, void* rhs, int typeId, int result);
long long QMetaType_Flags(void* ptr);
Expand Down
6 changes: 3 additions & 3 deletions dbus/dbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1627,7 +1627,7 @@ class MyQDBusPendingCallWatcher: public QDBusPendingCallWatcher
{
public:
MyQDBusPendingCallWatcher(const QDBusPendingCall &call, QObject *parent = Q_NULLPTR) : QDBusPendingCallWatcher(call, parent) {QDBusPendingCallWatcher_QDBusPendingCallWatcher_QRegisterMetaType();};
void Signal_Finished(QDBusPendingCallWatcher * self) { callbackQDBusPendingCallWatcher_Finished(this, self); };
void Signal_Finished(QDBusPendingCallWatcher * se) { callbackQDBusPendingCallWatcher_Finished(this, se); };
~MyQDBusPendingCallWatcher() { callbackQDBusPendingCallWatcher_DestroyQDBusPendingCallWatcher(this); };
void childEvent(QChildEvent * event) { callbackQDBusPendingCallWatcher_ChildEvent(this, event); };
void connectNotify(const QMetaMethod & sign) { callbackQDBusPendingCallWatcher_ConnectNotify(this, const_cast<QMetaMethod*>(&sign)); };
Expand Down Expand Up @@ -1662,9 +1662,9 @@ void QDBusPendingCallWatcher_DisconnectFinished(void* ptr)
QObject::disconnect(static_cast<QDBusPendingCallWatcher*>(ptr), static_cast<void (QDBusPendingCallWatcher::*)(QDBusPendingCallWatcher *)>(&QDBusPendingCallWatcher::finished), static_cast<MyQDBusPendingCallWatcher*>(ptr), static_cast<void (MyQDBusPendingCallWatcher::*)(QDBusPendingCallWatcher *)>(&MyQDBusPendingCallWatcher::Signal_Finished));
}

void QDBusPendingCallWatcher_Finished(void* ptr, void* self)
void QDBusPendingCallWatcher_Finished(void* ptr, void* se)
{
static_cast<QDBusPendingCallWatcher*>(ptr)->finished(static_cast<QDBusPendingCallWatcher*>(self));
static_cast<QDBusPendingCallWatcher*>(ptr)->finished(static_cast<QDBusPendingCallWatcher*>(se));
}

char QDBusPendingCallWatcher_IsFinished(void* ptr)
Expand Down
16 changes: 8 additions & 8 deletions dbus/dbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -3494,24 +3494,24 @@ func NewQDBusPendingCallWatcher(call QDBusPendingCall_ITF, parent core.QObject_I
}

//export callbackQDBusPendingCallWatcher_Finished
func callbackQDBusPendingCallWatcher_Finished(ptr unsafe.Pointer, self unsafe.Pointer) {
func callbackQDBusPendingCallWatcher_Finished(ptr unsafe.Pointer, se unsafe.Pointer) {
if signal := qt.GetSignal(ptr, "finished"); signal != nil {
(*(*func(*QDBusPendingCallWatcher))(signal))(NewQDBusPendingCallWatcherFromPointer(self))
(*(*func(*QDBusPendingCallWatcher))(signal))(NewQDBusPendingCallWatcherFromPointer(se))
}

}

func (ptr *QDBusPendingCallWatcher) ConnectFinished(f func(self *QDBusPendingCallWatcher)) {
func (ptr *QDBusPendingCallWatcher) ConnectFinished(f func(se *QDBusPendingCallWatcher)) {
if ptr.Pointer() != nil {

if !qt.ExistsSignal(ptr.Pointer(), "finished") {
C.QDBusPendingCallWatcher_ConnectFinished(ptr.Pointer(), C.longlong(qt.ConnectionType(ptr.Pointer(), "finished")))
}

if signal := qt.LendSignal(ptr.Pointer(), "finished"); signal != nil {
f := func(self *QDBusPendingCallWatcher) {
(*(*func(*QDBusPendingCallWatcher))(signal))(self)
f(self)
f := func(se *QDBusPendingCallWatcher) {
(*(*func(*QDBusPendingCallWatcher))(signal))(se)
f(se)
}
qt.ConnectSignal(ptr.Pointer(), "finished", unsafe.Pointer(&f))
} else {
Expand All @@ -3527,9 +3527,9 @@ func (ptr *QDBusPendingCallWatcher) DisconnectFinished() {
}
}

func (ptr *QDBusPendingCallWatcher) Finished(self QDBusPendingCallWatcher_ITF) {
func (ptr *QDBusPendingCallWatcher) Finished(se QDBusPendingCallWatcher_ITF) {
if ptr.Pointer() != nil {
C.QDBusPendingCallWatcher_Finished(ptr.Pointer(), PointerFromQDBusPendingCallWatcher(self))
C.QDBusPendingCallWatcher_Finished(ptr.Pointer(), PointerFromQDBusPendingCallWatcher(se))
}
}

Expand Down
2 changes: 1 addition & 1 deletion dbus/dbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ void QDBusPendingCall_DestroyQDBusPendingCall(void* ptr);
void* QDBusPendingCallWatcher_NewQDBusPendingCallWatcher(void* call, void* parent);
void QDBusPendingCallWatcher_ConnectFinished(void* ptr, long long t);
void QDBusPendingCallWatcher_DisconnectFinished(void* ptr);
void QDBusPendingCallWatcher_Finished(void* ptr, void* self);
void QDBusPendingCallWatcher_Finished(void* ptr, void* se);
char QDBusPendingCallWatcher_IsFinished(void* ptr);
void QDBusPendingCallWatcher_WaitForFinished(void* ptr);
void QDBusPendingCallWatcher_DestroyQDBusPendingCallWatcher(void* ptr);
Expand Down
2 changes: 1 addition & 1 deletion flutter/widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func RunOnMainBlocking(f func()) {
}

done := make(chan bool, 0)
interop.Helper.RunOnMainThread(func() { f(); done <- true })
interop.MainThreadHelper.RunOnMainThread(func() { f(); done <- true })
<-done
}

Expand Down
4 changes: 2 additions & 2 deletions gui/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12149,9 +12149,9 @@ void* QOpenGLContext_QOpenGLContext_GlobalShareContext()
return QOpenGLContext::globalShareContext();
}

char QOpenGLContext_HasExtension(void* ptr, void* extension)
char QOpenGLContext_HasExtension(void* ptr, void* extensi)
{
return static_cast<QOpenGLContext*>(ptr)->hasExtension(*static_cast<QByteArray*>(extension));
return static_cast<QOpenGLContext*>(ptr)->hasExtension(*static_cast<QByteArray*>(extensi));
}

char QOpenGLContext_IsOpenGLES(void* ptr)
Expand Down
4 changes: 2 additions & 2 deletions gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -26175,9 +26175,9 @@ func (ptr *QOpenGLContext) GlobalShareContext() *QOpenGLContext {
return tmpValue
}

func (ptr *QOpenGLContext) HasExtension(extension core.QByteArray_ITF) bool {
func (ptr *QOpenGLContext) HasExtension(extensi core.QByteArray_ITF) bool {
if ptr.Pointer() != nil {
return int8(C.QOpenGLContext_HasExtension(ptr.Pointer(), core.PointerFromQByteArray(extension))) != 0
return int8(C.QOpenGLContext_HasExtension(ptr.Pointer(), core.PointerFromQByteArray(extensi))) != 0
}
return false
}
Expand Down
2 changes: 1 addition & 1 deletion gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -1955,7 +1955,7 @@ void* QOpenGLContext_Functions(void* ptr);
void* QOpenGLContext_GetProcAddress(void* ptr, void* procName);
void* QOpenGLContext_GetProcAddress2(void* ptr, char* procName);
void* QOpenGLContext_QOpenGLContext_GlobalShareContext();
char QOpenGLContext_HasExtension(void* ptr, void* extension);
char QOpenGLContext_HasExtension(void* ptr, void* extensi);
char QOpenGLContext_IsOpenGLES(void* ptr);
char QOpenGLContext_IsValid(void* ptr);
char QOpenGLContext_MakeCurrent(void* ptr, void* surface);
Expand Down
26 changes: 8 additions & 18 deletions internal/binding/converter/body_input_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,7 @@ func GoInputParametersForC(function *parser.Function) string {
if function.SignalMode == "" {
for _, parameter := range function.Parameters {
if parameter.PureGoType != "" && !(parameter.Value == "QMap<QString, QVariant>" || parameter.Value == "QList<QVariant>") && !parser.IsBlackListedPureGoType(parameter.PureGoType) {
input = append(input, GoInput(fmt.Sprintf("uintptr(unsafe.Pointer(%v%v))",
func() string {
if !strings.HasPrefix(parameter.PureGoType, "*") {
return "&"
}
return ""
}(), parser.CleanName(parameter.Name, parameter.Value)), parameter.Value, function, parameter.PureGoType))
input = append(input, GoInput(fmt.Sprintf("%vTID", parser.CleanName(parameter.Name, parameter.Value)), parameter.Value, function, parameter.PureGoType))
} else {
var alloc = GoInput(parameter.Name, parameter.Value, function, parameter.PureGoType)
if strings.Contains(alloc, "C.CString") || strings.Contains(alloc, "qt.GoBoolToInt(*") || strings.Contains(alloc, "*C.char") || strings.Contains(alloc, "C.long(int32(*") {
Expand Down Expand Up @@ -72,17 +66,13 @@ func GoInputParametersForJS(function *parser.Function) string {
for _, parameter := range function.Parameters {
if parameter.PureGoType != "" && !(parameter.Value == "QMap<QString, QVariant>" || parameter.Value == "QList<QVariant>") && !parser.IsBlackListedPureGoType(parameter.PureGoType) {
if parser.UseWasm() {
if parameter.PureGoType != "" && !(parameter.Value == "QMap<QString, QVariant>" || parameter.Value == "QList<QVariant>") && !parser.IsBlackListedPureGoType(parameter.PureGoType) {
input = append(input, GoInput(fmt.Sprintf("unsafe.Pointer(%v%v)",
func() string {
if !strings.HasPrefix(parameter.PureGoType, "*") {
return "&"
}
return ""
}(), parser.CleanName(parameter.Name, parameter.Value)), parameter.Value, function, parameter.PureGoType))
} else {
input = append(input, GoInputJS(parser.CleanName(parameter.Name, parameter.Value), parameter.Value, function, parameter.PureGoType))
}
input = append(input, GoInput(fmt.Sprintf("unsafe.Pointer(%v%v)",
func() string {
if !strings.HasPrefix(parameter.PureGoType, "*") {
return "&"
}
return ""
}(), parser.CleanName(parameter.Name, parameter.Value)), parameter.Value, function, parameter.PureGoType))
} else {
input = append(input, GoInputJS(fmt.Sprintf("%vTID", parser.CleanName(parameter.Name, parameter.Value)), parameter.Value, function, parameter.PureGoType))
}
Expand Down
74 changes: 71 additions & 3 deletions internal/binding/files/utils-qml.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package qml

import (
"encoding/json"
"math"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"unsafe"
Expand All @@ -17,6 +19,18 @@ var (

finalizerMap = make(map[unsafe.Pointer][]*core.QObject)
finalizerMapMutex sync.Mutex

//needed only for interop --->
ReturnPointersAsStrings bool

syncCallIntoRemoteChan = make(chan string, 0)
syncCallIntoRemoteReturnChan = make(chan string, 0)

fromJsToRefReturnsOnChan bool
fromJsToRefReturnChan = make(chan []reflect.Value, 0)

Z_wrapperFunctionReturnChan = make(chan *QJSValue, 0)
//needed only for interop <---
)

type ptr_itf interface {
Expand Down Expand Up @@ -203,6 +217,31 @@ func Z_wrapperFunction(jsvals *QJSValue) *QJSValue {
}

ret := m.Call(input)

//needed only for interop --->
if fromJsToRefReturnsOnChan {
fromJsToRefReturnsOnChan = false
go func() {
ret = <-fromJsToRefReturnChan

if len(ret) == 0 {
Z_wrapperFunctionReturnChan <- NewQJSValue(QJSValue__UndefinedValue)
return
}

rret := engine.NewGoType(ret[0].Interface())
if reflect.TypeOf(ret[0].Interface()).Implements(reflect.TypeOf((*core.QObject_ITF)(nil)).Elem()) { //TODO: check for destroyed signal instead, or simply override the destructor instead ?
if qt.ExistsSignal(ret[0].Interface().(ptr_itf).Pointer(), "destroyed") {
engine.GlobalObject().Property("___connectDestroyed").Call([]*QJSValue{rret}) //TODO: connect destroyed/destructor from go instead ?
}
}

Z_wrapperFunctionReturnChan <- rret
}()
return NewQJSValue(QJSValue__UndefinedValue)
}
//needed only for interop <---

if len(ret) == 0 {
return NewQJSValue(QJSValue__UndefinedValue)
}
Expand Down Expand Up @@ -256,10 +295,35 @@ func (ptr *QJSEngine) fromJsToRef(tofi reflect.Type, jsval *QJSValue) reflect.Va
for i, arg := range args {
input[i] = ptr.NewGoType(arg.Interface())
}
if ret := jsval.Call(input); tofi.NumOut() != 0 {
return []reflect.Value{ptr.fromJsToRef(tofi.Out(0), ret)}
ret := jsval.Call(input)

//the default path to return on this function
if !(ret.IsObject() && ret.Property("___earlyReturn").ToString() == "true") {
if tofi.NumOut() != 0 {
return []reflect.Value{ptr.fromJsToRef(tofi.Out(0), ret)}
}
return nil
}

//needed only for interop --->
fromJsToRefReturnsOnChan = true

syncCallIntoRemoteChan <- string(ret.Property("___data").ToString())
go func() {
var o interface{}
json.Unmarshal([]byte(<-syncCallIntoRemoteReturnChan), &o)
if tofi.NumOut() != 0 {
fromJsToRefReturnChan <- []reflect.Value{ptr.fromJsToRef(tofi.Out(0), ptr.ToScriptValue(core.NewQVariant1(o)))}
} else {
fromJsToRefReturnChan <- nil
}
}()

if tofi.NumOut() != 0 {
return []reflect.Value{reflect.ValueOf("___earlyReturn")}
}
return nil
//needed only for interop <---
})

//TODO: merge into (*core.QVariant).ToGoType ? >>>
Expand Down Expand Up @@ -586,7 +650,11 @@ func (ptr *QJSEngine) makeFuncWrapper(fn string) *QJSValue {
}

func (ptr *QJSEngine) makeObjectWrapper(in interface{}, jsv *QJSValue) {
jsv.SetProperty("___pointer", ptr.ToScriptValue(core.NewQVariant1(uint64(uintptr(in.(ptr_itf).Pointer()))))) //TODO: can be shortened once NewQVariant1 supports unsafe.Pointer
if ReturnPointersAsStrings {
jsv.SetProperty("___pointer", ptr.ToScriptValue(core.NewQVariant1(strconv.FormatUint(uint64(uintptr(in.(ptr_itf).Pointer())), 10)))) //TODO: can be shortened once NewQVariant1 supports unsafe.Pointer
} else {
jsv.SetProperty("___pointer", ptr.ToScriptValue(core.NewQVariant1(uint64(uintptr(in.(ptr_itf).Pointer()))))) //TODO: can be shortened once NewQVariant1 supports unsafe.Pointer
}

rv := reflect.ValueOf(in)

Expand Down
7 changes: 6 additions & 1 deletion internal/binding/parser/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,12 @@ func CleanName(name, value string) string {
"time",
"hex",
"script",
"final":
"final",
"where",
"extension",
"protocol",
"self",
"repeat":
{
return name[:len(name)-2]
}
Expand Down
Loading

0 comments on commit 7f61353

Please sign in to comment.