Skip to content

Commit 826359a

Browse files
committed
Porting go-qml to Go 1.6
Go 1.6 cannot have Go pointer stored into the cgo space. So instead we need to store all Go values in a map and pass a key to the cgo space. When needed the key can be used to retrieve the go value from the map.
1 parent 2ee7e5f commit 826359a

File tree

7 files changed

+93
-75
lines changed

7 files changed

+93
-75
lines changed

bridge.go

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ func init() {
3838
guiMainRef = cdata.Ref()
3939
}
4040

41+
// foldRefs holds all fold values that are created. Since Go Pointer
42+
// are not allowed to be held by cgo. We need a lookup table to
43+
// interface the two space.
44+
var foldRefs = make(map[uintptr]*valueFold)
45+
4146
// Run runs the main QML event loop, runs f, and then terminates the
4247
// event loop once f returns.
4348
//
@@ -210,6 +215,16 @@ const (
210215
jsOwner
211216
)
212217

218+
func storeFold(fold *valueFold) C.GoRef {
219+
foldRef := uintptr(unsafe.Pointer(fold))
220+
foldRefs[foldRef] = fold
221+
return C.GoRef(foldRef)
222+
}
223+
224+
func restoreFold(ref uintptr) *valueFold {
225+
return foldRefs[ref]
226+
}
227+
213228
// wrapGoValue creates a new GoValue object in C++ land wrapping
214229
// the Go value contained in the given interface.
215230
//
@@ -251,7 +266,7 @@ func wrapGoValue(engine *Engine, gvalue interface{}, owner valueOwner) (cvalue u
251266
gvalue: gvalue,
252267
owner: owner,
253268
}
254-
fold.cvalue = C.newGoValue(unsafe.Pointer(fold), typeInfo(gvalue), parent)
269+
fold.cvalue = C.newGoValue(storeFold(fold), typeInfo(gvalue), parent)
255270
if prev != nil {
256271
// Put new fold first so the single cppOwner, if any, is always the first entry.
257272
fold.next = prev
@@ -289,7 +304,7 @@ func addrOf(gvalue interface{}) uintptr {
289304
var typeNew = make(map[*valueFold]bool)
290305

291306
//export hookGoValueTypeNew
292-
func hookGoValueTypeNew(cvalue unsafe.Pointer, specp unsafe.Pointer) (foldp unsafe.Pointer) {
307+
func hookGoValueTypeNew(cvalue unsafe.Pointer, specp unsafe.Pointer) (foldr C.GoRef) {
293308
// Initialization is postponed until the engine is available, so that
294309
// we can hand Init the qml.Object that represents the object.
295310
init := reflect.ValueOf((*TypeSpec)(specp).Init)
@@ -299,15 +314,17 @@ func hookGoValueTypeNew(cvalue unsafe.Pointer, specp unsafe.Pointer) (foldp unsa
299314
cvalue: cvalue,
300315
owner: jsOwner,
301316
}
317+
302318
typeNew[fold] = true
303319
//fmt.Printf("[DEBUG] value alive (type-created): cvalue=%x gvalue=%x/%#v\n", fold.cvalue, addrOf(fold.gvalue), fold.gvalue)
304320
stats.valuesAlive(+1)
305-
return unsafe.Pointer(fold)
321+
return storeFold(fold)
306322
}
307323

308324
//export hookGoValueDestroyed
309-
func hookGoValueDestroyed(enginep unsafe.Pointer, foldp unsafe.Pointer) {
310-
fold := (*valueFold)(foldp)
325+
func hookGoValueDestroyed(enginep unsafe.Pointer, foldr uintptr) {
326+
fold := restoreFold(foldr)
327+
311328
engine := fold.engine
312329
if engine == nil {
313330
before := len(typeNew)
@@ -360,8 +377,8 @@ func deref(value reflect.Value) reflect.Value {
360377
}
361378

362379
//export hookGoValueReadField
363-
func hookGoValueReadField(enginep, foldp unsafe.Pointer, reflectIndex, getIndex, setIndex C.int, resultdv *C.DataValue) {
364-
fold := ensureEngine(enginep, foldp)
380+
func hookGoValueReadField(enginep unsafe.Pointer, foldr uintptr, reflectIndex, getIndex, setIndex C.int, resultdv *C.DataValue) {
381+
fold := ensureEngine(enginep, foldr)
365382

366383
var field reflect.Value
367384
if getIndex >= 0 {
@@ -376,7 +393,7 @@ func hookGoValueReadField(enginep, foldp unsafe.Pointer, reflectIndex, getIndex,
376393
// TODO Handle getters that return []qml.Object.
377394
// TODO Handle other GoValue slices (!= []qml.Object).
378395
resultdv.dataType = C.DTListProperty
379-
*(*unsafe.Pointer)(unsafe.Pointer(&resultdv.data)) = C.newListProperty(foldp, C.intptr_t(reflectIndex), C.intptr_t(setIndex))
396+
*(*unsafe.Pointer)(unsafe.Pointer(&resultdv.data)) = C.newListProperty(C.GoRef(foldr), C.intptr_t(reflectIndex), C.intptr_t(setIndex))
380397
return
381398
}
382399

@@ -406,8 +423,8 @@ func hookGoValueReadField(enginep, foldp unsafe.Pointer, reflectIndex, getIndex,
406423
}
407424

408425
//export hookGoValueWriteField
409-
func hookGoValueWriteField(enginep, foldp unsafe.Pointer, reflectIndex, setIndex C.int, assigndv *C.DataValue) {
410-
fold := ensureEngine(enginep, foldp)
426+
func hookGoValueWriteField(enginep unsafe.Pointer, foldr uintptr, reflectIndex, setIndex C.int, assigndv *C.DataValue) {
427+
fold := ensureEngine(enginep, foldr)
411428
v := reflect.ValueOf(fold.gvalue)
412429
ve := v
413430
for ve.Type().Kind() == reflect.Ptr {
@@ -483,8 +500,8 @@ var (
483500
)
484501

485502
//export hookGoValueCallMethod
486-
func hookGoValueCallMethod(enginep, foldp unsafe.Pointer, reflectIndex C.int, args *C.DataValue) {
487-
fold := ensureEngine(enginep, foldp)
503+
func hookGoValueCallMethod(enginep unsafe.Pointer, foldr uintptr, reflectIndex C.int, args *C.DataValue) {
504+
fold := ensureEngine(enginep, foldr)
488505
v := reflect.ValueOf(fold.gvalue)
489506

490507
// TODO Must assert that v is necessarily a pointer here, but we shouldn't have to manipulate
@@ -548,7 +565,7 @@ func printPaintPanic() {
548565
}
549566

550567
//export hookGoValuePaint
551-
func hookGoValuePaint(enginep, foldp unsafe.Pointer, reflectIndex C.intptr_t) {
568+
func hookGoValuePaint(enginep unsafe.Pointer, foldr uintptr, reflectIndex C.intptr_t) {
552569
// Besides a convenience this is a workaround for http://golang.org/issue/8588
553570
defer printPaintPanic()
554571
defer atomic.StoreUintptr(&guiPaintRef, 0)
@@ -557,7 +574,7 @@ func hookGoValuePaint(enginep, foldp unsafe.Pointer, reflectIndex C.intptr_t) {
557574
// so no two paintings should be happening at the same time.
558575
atomic.StoreUintptr(&guiPaintRef, cdata.Ref())
559576

560-
fold := ensureEngine(enginep, foldp)
577+
fold := ensureEngine(enginep, foldr)
561578
if fold.init.IsValid() {
562579
return
563580
}
@@ -568,8 +585,8 @@ func hookGoValuePaint(enginep, foldp unsafe.Pointer, reflectIndex C.intptr_t) {
568585
method.Call([]reflect.Value{reflect.ValueOf(painter)})
569586
}
570587

571-
func ensureEngine(enginep, foldp unsafe.Pointer) *valueFold {
572-
fold := (*valueFold)(foldp)
588+
func ensureEngine(enginep unsafe.Pointer, foldr uintptr) *valueFold {
589+
fold := restoreFold(foldr)
573590
if fold.engine != nil {
574591
if fold.init.IsValid() {
575592
initGoType(fold)
@@ -637,22 +654,22 @@ func listSlice(fold *valueFold, reflectIndex C.intptr_t) *[]Object {
637654
}
638655

639656
//export hookListPropertyAt
640-
func hookListPropertyAt(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t, index C.int) (objp unsafe.Pointer) {
641-
fold := (*valueFold)(foldp)
657+
func hookListPropertyAt(foldr uintptr, reflectIndex, setIndex C.intptr_t, index C.int) (objp unsafe.Pointer) {
658+
fold := restoreFold(foldr)
642659
slice := listSlice(fold, reflectIndex)
643660
return (*slice)[int(index)].Common().addr
644661
}
645662

646663
//export hookListPropertyCount
647-
func hookListPropertyCount(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t) C.int {
648-
fold := (*valueFold)(foldp)
664+
func hookListPropertyCount(foldr uintptr, reflectIndex, setIndex C.intptr_t) C.int {
665+
fold := restoreFold(foldr)
649666
slice := listSlice(fold, reflectIndex)
650667
return C.int(len(*slice))
651668
}
652669

653670
//export hookListPropertyAppend
654-
func hookListPropertyAppend(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t, objp unsafe.Pointer) {
655-
fold := (*valueFold)(foldp)
671+
func hookListPropertyAppend(foldr uintptr, reflectIndex, setIndex C.intptr_t, objp unsafe.Pointer) {
672+
fold := restoreFold(foldr)
656673
slice := listSlice(fold, reflectIndex)
657674
var objdv C.DataValue
658675
objdv.dataType = C.DTObject
@@ -666,8 +683,8 @@ func hookListPropertyAppend(foldp unsafe.Pointer, reflectIndex, setIndex C.intpt
666683
}
667684

668685
//export hookListPropertyClear
669-
func hookListPropertyClear(foldp unsafe.Pointer, reflectIndex, setIndex C.intptr_t) {
670-
fold := (*valueFold)(foldp)
686+
func hookListPropertyClear(foldr uintptr, reflectIndex, setIndex C.intptr_t) {
687+
fold := restoreFold(foldr)
671688
slice := listSlice(fold, reflectIndex)
672689
newslice := (*slice)[0:0]
673690
if setIndex >= 0 {

cpp/capi.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -543,17 +543,17 @@ int objectIsView(QObject_ *object)
543543
return dynamic_cast<QQuickView *>(qobject) ? 1 : 0;
544544
}
545545

546-
error *objectGoAddr(QObject_ *object, GoAddr **addr)
546+
error *objectGoRef(QObject_ *object, GoRef *ref)
547547
{
548548
QObject *qobject = static_cast<QObject *>(object);
549549
GoValue *goValue = dynamic_cast<GoValue *>(qobject);
550550
if (goValue) {
551-
*addr = goValue->addr;
551+
*ref = goValue->ref;
552552
return 0;
553553
}
554554
GoPaintedValue *goPaintedValue = dynamic_cast<GoPaintedValue *>(qobject);
555555
if (goPaintedValue) {
556-
*addr = goPaintedValue->addr;
556+
*ref= goPaintedValue->ref;
557557
return 0;
558558
}
559559
return errorf("QML object is not backed by a Go value");
@@ -571,13 +571,13 @@ void delString(QString_ *s)
571571
delete reinterpret_cast<QString *>(s);
572572
}
573573

574-
GoValue_ *newGoValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject_ *parent)
574+
GoValue_ *newGoValue(GoRef ref, GoTypeInfo *typeInfo, QObject_ *parent)
575575
{
576576
QObject *qparent = reinterpret_cast<QObject *>(parent);
577577
if (typeInfo->paint) {
578-
return new GoPaintedValue(addr, typeInfo, qparent);
578+
return new GoPaintedValue(ref, typeInfo, qparent);
579579
}
580-
return new GoValue(addr, typeInfo, qparent);
580+
return new GoValue(ref, typeInfo, qparent);
581581
}
582582

583583
void goValueActivate(GoValue_ *value, GoTypeInfo *typeInfo, int addrOffset)
@@ -749,13 +749,13 @@ void packDataValue(QVariant_ *var, DataValue *value)
749749
GoValue *goValue = dynamic_cast<GoValue *>(qobject);
750750
if (goValue) {
751751
value->dataType = DTGoAddr;
752-
*(void **)(value->data) = goValue->addr;
752+
*(uintptr_t*)(value->data) = goValue->ref;
753753
break;
754754
}
755755
GoPaintedValue *goPaintedValue = dynamic_cast<GoPaintedValue *>(qobject);
756756
if (goPaintedValue) {
757757
value->dataType = DTGoAddr;
758-
*(void **)(value->data) = goPaintedValue->addr;
758+
*(uintptr_t*)(value->data) = goPaintedValue->ref;
759759
break;
760760
}
761761
value->dataType = DTObject;
@@ -813,28 +813,28 @@ QVariantList_ *newVariantList(DataValue *list, int len)
813813

814814
QObject *listPropertyAt(QQmlListProperty<QObject> *list, int i)
815815
{
816-
return reinterpret_cast<QObject *>(hookListPropertyAt(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, i));
816+
return reinterpret_cast<QObject *>(hookListPropertyAt((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, i));
817817
}
818818

819819
int listPropertyCount(QQmlListProperty<QObject> *list)
820820
{
821-
return hookListPropertyCount(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2);
821+
return hookListPropertyCount((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2);
822822
}
823823

824824
void listPropertyAppend(QQmlListProperty<QObject> *list, QObject *obj)
825825
{
826-
hookListPropertyAppend(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, obj);
826+
hookListPropertyAppend((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2, obj);
827827
}
828828

829829
void listPropertyClear(QQmlListProperty<QObject> *list)
830830
{
831-
hookListPropertyClear(list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2);
831+
hookListPropertyClear((uintptr_t)list->data, (intptr_t)list->dummy1, (intptr_t)list->dummy2);
832832
}
833833

834-
QQmlListProperty_ *newListProperty(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex)
834+
QQmlListProperty_ *newListProperty(GoRef ref, intptr_t reflectIndex, intptr_t setIndex)
835835
{
836836
QQmlListProperty<QObject> *list = new QQmlListProperty<QObject>();
837-
list->data = addr;
837+
list->data = (void*)ref;
838838
list->dummy1 = (void*)reflectIndex;
839839
list->dummy2 = (void*)setIndex;
840840
list->at = listPropertyAt;

cpp/capi.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typedef void QMessageLogContext_;
2929
typedef void QImage_;
3030
typedef void GoValue_;
3131
typedef void GoAddr;
32+
typedef uintptr_t GoRef;
3233
typedef void GoTypeSpec_;
3334

3435
typedef char error;
@@ -141,7 +142,7 @@ int objectIsComponent(QObject_ *object);
141142
int objectIsWindow(QObject_ *object);
142143
int objectIsView(QObject_ *object);
143144
error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, void *func, int argsLen);
144-
error *objectGoAddr(QObject_ *object, GoAddr **addr);
145+
error *objectGoRef(QObject_ *object, GoRef *ref);
145146

146147
QQmlComponent_ *newComponent(QQmlEngine_ *engine, QObject_ *parent);
147148
void componentLoadURL(QQmlComponent_ *component, const char *url, int urlLen);
@@ -166,15 +167,15 @@ const unsigned char *imageConstBits(QImage_ *image);
166167
QString_ *newString(const char *data, int len);
167168
void delString(QString_ *s);
168169

169-
GoValue_ *newGoValue(GoAddr *addr, GoTypeInfo *typeInfo, QObject_ *parent);
170+
GoValue_ *newGoValue(GoRef ref, GoTypeInfo *typeInfo, QObject_ *parent);
170171
void goValueActivate(GoValue_ *value, GoTypeInfo *typeInfo, int addrOffset);
171172

172173
void packDataValue(QVariant_ *var, DataValue *result);
173174
void unpackDataValue(DataValue *value, QVariant_ *result);
174175

175176
QVariantList_ *newVariantList(DataValue *list, int len);
176177

177-
QQmlListProperty_ *newListProperty(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex);
178+
QQmlListProperty_ *newListProperty(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);
178179

179180
int registerType(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ *spec);
180181
int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ *spec);
@@ -183,21 +184,21 @@ void installLogHandler();
183184

184185
void hookIdleTimer();
185186
void hookLogHandler(LogMessage *message);
186-
void hookGoValueReadField(QQmlEngine_ *engine, GoAddr *addr, int memberIndex, int getIndex, int setIndex, DataValue *result);
187-
void hookGoValueWriteField(QQmlEngine_ *engine, GoAddr *addr, int memberIndex, int setIndex, DataValue *assign);
188-
void hookGoValueCallMethod(QQmlEngine_ *engine, GoAddr *addr, int memberIndex, DataValue *result);
189-
void hookGoValueDestroyed(QQmlEngine_ *engine, GoAddr *addr);
190-
void hookGoValuePaint(QQmlEngine_ *engine, GoAddr *addr, intptr_t reflextIndex);
187+
void hookGoValueReadField(QQmlEngine_ *engine, GoRef ref, int memberIndex, int getIndex, int setIndex, DataValue *result);
188+
void hookGoValueWriteField(QQmlEngine_ *engine, GoRef ref, int memberIndex, int setIndex, DataValue *assign);
189+
void hookGoValueCallMethod(QQmlEngine_ *engine, GoRef ref, int memberIndex, DataValue *result);
190+
void hookGoValueDestroyed(QQmlEngine_ *engine, GoRef ref);
191+
void hookGoValuePaint(QQmlEngine_ *engine, GoRef ref, intptr_t reflextIndex);
191192
QImage_ *hookRequestImage(void *imageFunc, char *id, int idLen, int width, int height);
192-
GoAddr *hookGoValueTypeNew(GoValue_ *value, GoTypeSpec_ *spec);
193+
uintptr_t hookGoValueTypeNew(GoValue_ *value, GoTypeSpec_ *spec);
193194
void hookWindowHidden(QObject_ *addr);
194195
void hookSignalCall(QQmlEngine_ *engine, void *func, DataValue *params);
195196
void hookSignalDisconnect(void *func);
196197
void hookPanic(char *message);
197-
int hookListPropertyCount(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex);
198-
QObject_ *hookListPropertyAt(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex, int i);
199-
void hookListPropertyAppend(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex, QObject_ *obj);
200-
void hookListPropertyClear(GoAddr *addr, intptr_t reflectIndex, intptr_t setIndex);
198+
int hookListPropertyCount(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);
199+
QObject_ *hookListPropertyAt(GoRef ref, intptr_t reflectIndex, intptr_t setIndex, int i);
200+
void hookListPropertyAppend(GoRef ref, intptr_t reflectIndex, intptr_t setIndex, QObject_ *obj);
201+
void hookListPropertyClear(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);
201202

202203
void registerResourceData(int version, char *tree, char *name, char *data);
203204
void unregisterResourceData(int version, char *tree, char *name, char *data);

0 commit comments

Comments
 (0)