Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go1.6 port #8

Merged
merged 5 commits into from
Apr 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 56 additions & 35 deletions bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ func init() {
guiMainRef = cdata.Ref()
}

// foldRefs holds all fold values that are created. Since Go Pointer
// are not allowed to be held by cgo. We need a lookup table to
// interface the two space.
var foldRefs = make(map[uintptr]*valueFold)

// Run runs the main QML event loop, runs f, and then terminates the
// event loop once f returns.
//
Expand Down Expand Up @@ -208,23 +203,42 @@ type valueFold struct {
owner valueOwner
}

// cgoFolds holds all fold values that get reference to on the cgo space.
// Since Go Pointer are not allowed to be held by cgo. We need a lookup
// table to interface the two space.
var cgoFolds = make(map[C.GoRef]*valueFold)

// GoRef index the valueFold value and return a lookup
// key (C.GoRef), so that we can retrieve the fold using
// the C.GoRef. need to cross between go and cgo
func (f *valueFold) goRef() C.GoRef {
ref := C.GoRef(uintptr(unsafe.Pointer(f)))
cgoFolds[ref] = f
return ref
}

// destroyRef remove the valueFold reference from the lookup table.
func (f *valueFold) destroyRef() {
ref := C.GoRef(uintptr(unsafe.Pointer(f)))
delete(cgoFolds, ref)
}

// getFoldFromGoRef return the valueFold value located at ref
func getFoldFromGoRef(ref C.GoRef) *valueFold {
fold := cgoFolds[ref]
if fold == nil {
panic("cannot find fold go reference")
}
return fold
}

type valueOwner uint8

const (
cppOwner = 1 << iota
jsOwner
)

func storeFold(fold *valueFold) C.GoRef {
foldRef := uintptr(unsafe.Pointer(fold))
foldRefs[foldRef] = fold
return C.GoRef(foldRef)
}

func restoreFold(ref uintptr) *valueFold {
return foldRefs[ref]
}

// wrapGoValue creates a new GoValue object in C++ land wrapping
// the Go value contained in the given interface.
//
Expand Down Expand Up @@ -266,7 +280,7 @@ func wrapGoValue(engine *Engine, gvalue interface{}, owner valueOwner) (cvalue u
gvalue: gvalue,
owner: owner,
}
fold.cvalue = C.newGoValue(storeFold(fold), typeInfo(gvalue), parent)
fold.cvalue = C.newGoValue(fold.goRef(), typeInfo(gvalue), parent)
if prev != nil {
// Put new fold first so the single cppOwner, if any, is always the first entry.
fold.next = prev
Expand Down Expand Up @@ -304,10 +318,15 @@ func addrOf(gvalue interface{}) uintptr {
var typeNew = make(map[*valueFold]bool)

//export hookGoValueTypeNew
func hookGoValueTypeNew(cvalue unsafe.Pointer, specp unsafe.Pointer) (foldr C.GoRef) {
func hookGoValueTypeNew(cvalue unsafe.Pointer, specr C.GoTypeSpec_) (foldr C.GoRef) {
// Initialization is postponed until the engine is available, so that
// we can hand Init the qml.Object that represents the object.
init := reflect.ValueOf((*TypeSpec)(specp).Init)
spec := types[specr]
if spec == nil {
panic("cannot find the specified TypeSpec")
}

init := reflect.ValueOf(spec.Init)
fold := &valueFold{
init: init,
gvalue: reflect.New(init.Type().In(0).Elem()).Interface(),
Expand All @@ -318,17 +337,18 @@ func hookGoValueTypeNew(cvalue unsafe.Pointer, specp unsafe.Pointer) (foldr C.Go
typeNew[fold] = true
//fmt.Printf("[DEBUG] value alive (type-created): cvalue=%x gvalue=%x/%#v\n", fold.cvalue, addrOf(fold.gvalue), fold.gvalue)
stats.valuesAlive(+1)
return storeFold(fold)
return fold.goRef()
}

//export hookGoValueDestroyed
func hookGoValueDestroyed(enginep unsafe.Pointer, foldr uintptr) {
fold := restoreFold(foldr)
func hookGoValueDestroyed(enginep unsafe.Pointer, foldr C.GoRef) {
fold := getFoldFromGoRef(foldr)

engine := fold.engine
if engine == nil {
before := len(typeNew)
delete(typeNew, fold)
fold.destroyRef()
if len(typeNew) == before {
panic("destroying value without an associated engine; who created the value?")
}
Expand Down Expand Up @@ -359,6 +379,7 @@ func hookGoValueDestroyed(enginep unsafe.Pointer, foldr uintptr) {
delete(engines, engine.addr)
}
}
fold.destroyRef()
}
//fmt.Printf("[DEBUG] value destroyed: cvalue=%x gvalue=%x/%#v\n", fold.cvalue, addrOf(fold.gvalue), fold.gvalue)
stats.valuesAlive(-1)
Expand All @@ -377,7 +398,7 @@ func deref(value reflect.Value) reflect.Value {
}

//export hookGoValueReadField
func hookGoValueReadField(enginep unsafe.Pointer, foldr uintptr, reflectIndex, getIndex, setIndex C.int, resultdv *C.DataValue) {
func hookGoValueReadField(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex, getIndex, setIndex C.int, resultdv *C.DataValue) {
fold := ensureEngine(enginep, foldr)

var field reflect.Value
Expand Down Expand Up @@ -423,7 +444,7 @@ func hookGoValueReadField(enginep unsafe.Pointer, foldr uintptr, reflectIndex, g
}

//export hookGoValueWriteField
func hookGoValueWriteField(enginep unsafe.Pointer, foldr uintptr, reflectIndex, setIndex C.int, assigndv *C.DataValue) {
func hookGoValueWriteField(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex, setIndex C.int, assigndv *C.DataValue) {
fold := ensureEngine(enginep, foldr)
v := reflect.ValueOf(fold.gvalue)
ve := v
Expand Down Expand Up @@ -500,7 +521,7 @@ var (
)

//export hookGoValueCallMethod
func hookGoValueCallMethod(enginep unsafe.Pointer, foldr uintptr, reflectIndex C.int, args *C.DataValue) {
func hookGoValueCallMethod(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex C.int, args *C.DataValue) {
fold := ensureEngine(enginep, foldr)
v := reflect.ValueOf(fold.gvalue)

Expand Down Expand Up @@ -565,7 +586,7 @@ func printPaintPanic() {
}

//export hookGoValuePaint
func hookGoValuePaint(enginep unsafe.Pointer, foldr uintptr, reflectIndex C.intptr_t) {
func hookGoValuePaint(enginep unsafe.Pointer, foldr C.GoRef, reflectIndex C.intptr_t) {
// Besides a convenience this is a workaround for http://golang.org/issue/8588
defer printPaintPanic()
defer atomic.StoreUintptr(&guiPaintRef, 0)
Expand All @@ -585,8 +606,8 @@ func hookGoValuePaint(enginep unsafe.Pointer, foldr uintptr, reflectIndex C.intp
method.Call([]reflect.Value{reflect.ValueOf(painter)})
}

func ensureEngine(enginep unsafe.Pointer, foldr uintptr) *valueFold {
fold := restoreFold(foldr)
func ensureEngine(enginep unsafe.Pointer, foldr C.GoRef) *valueFold {
fold := getFoldFromGoRef(foldr)
if fold.engine != nil {
if fold.init.IsValid() {
initGoType(fold)
Expand Down Expand Up @@ -654,22 +675,22 @@ func listSlice(fold *valueFold, reflectIndex C.intptr_t) *[]Object {
}

//export hookListPropertyAt
func hookListPropertyAt(foldr uintptr, reflectIndex, setIndex C.intptr_t, index C.int) (objp unsafe.Pointer) {
fold := restoreFold(foldr)
func hookListPropertyAt(foldr C.GoRef, reflectIndex, setIndex C.intptr_t, index C.int) (objp unsafe.Pointer) {
fold := getFoldFromGoRef(foldr)
slice := listSlice(fold, reflectIndex)
return (*slice)[int(index)].Common().addr
}

//export hookListPropertyCount
func hookListPropertyCount(foldr uintptr, reflectIndex, setIndex C.intptr_t) C.int {
fold := restoreFold(foldr)
func hookListPropertyCount(foldr C.GoRef, reflectIndex, setIndex C.intptr_t) C.int {
fold := getFoldFromGoRef(foldr)
slice := listSlice(fold, reflectIndex)
return C.int(len(*slice))
}

//export hookListPropertyAppend
func hookListPropertyAppend(foldr uintptr, reflectIndex, setIndex C.intptr_t, objp unsafe.Pointer) {
fold := restoreFold(foldr)
func hookListPropertyAppend(foldr C.GoRef, reflectIndex, setIndex C.intptr_t, objp unsafe.Pointer) {
fold := getFoldFromGoRef(foldr)
slice := listSlice(fold, reflectIndex)
var objdv C.DataValue
objdv.dataType = C.DTObject
Expand All @@ -683,8 +704,8 @@ func hookListPropertyAppend(foldr uintptr, reflectIndex, setIndex C.intptr_t, ob
}

//export hookListPropertyClear
func hookListPropertyClear(foldr uintptr, reflectIndex, setIndex C.intptr_t) {
fold := restoreFold(foldr)
func hookListPropertyClear(foldr C.GoRef, reflectIndex, setIndex C.intptr_t) {
fold := getFoldFromGoRef(foldr)
slice := listSlice(fold, reflectIndex)
newslice := (*slice)[0:0]
if setIndex >= 0 {
Expand Down
2 changes: 1 addition & 1 deletion cpp/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ void objectSetParent(QObject_ *object, QObject_ *parent)
qobject->setParent(qparent);
}

error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, void *func, int argsLen)
error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, GoRef func, int argsLen)
{
QObject *qobject = reinterpret_cast<QObject *>(object);
QQmlEngine *qengine = reinterpret_cast<QQmlEngine *>(engine);
Expand Down
14 changes: 7 additions & 7 deletions cpp/capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ typedef void QImage_;
typedef void GoValue_;
typedef void GoAddr;
typedef uintptr_t GoRef;
typedef void GoTypeSpec_;
typedef uintptr_t GoTypeSpec_;

typedef char error;
error *errorf(const char *format, ...);
Expand Down Expand Up @@ -141,7 +141,7 @@ QQmlContext_ *objectContext(QObject_ *object);
int objectIsComponent(QObject_ *object);
int objectIsWindow(QObject_ *object);
int objectIsView(QObject_ *object);
error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, void *func, int argsLen);
error *objectConnect(QObject_ *object, const char *signal, int signalLen, QQmlEngine_ *engine, GoRef func, int argsLen);
error *objectGoRef(QObject_ *object, GoRef *ref);

QQmlComponent_ *newComponent(QQmlEngine_ *engine, QObject_ *parent);
Expand Down Expand Up @@ -177,8 +177,8 @@ QVariantList_ *newVariantList(DataValue *list, int len);

QQmlListProperty_ *newListProperty(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);

int registerType(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ *spec);
int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ *spec);
int registerType(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ spec);
int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *typeInfo, GoTypeSpec_ spec);

void installLogHandler();

Expand All @@ -190,10 +190,10 @@ void hookGoValueCallMethod(QQmlEngine_ *engine, GoRef ref, int memberIndex, Data
void hookGoValueDestroyed(QQmlEngine_ *engine, GoRef ref);
void hookGoValuePaint(QQmlEngine_ *engine, GoRef ref, intptr_t reflextIndex);
QImage_ *hookRequestImage(void *imageFunc, char *id, int idLen, int width, int height);
uintptr_t hookGoValueTypeNew(GoValue_ *value, GoTypeSpec_ *spec);
GoRef hookGoValueTypeNew(GoValue_ *value, GoTypeSpec_ spec);
void hookWindowHidden(QObject_ *addr);
void hookSignalCall(QQmlEngine_ *engine, void *func, DataValue *params);
void hookSignalDisconnect(void *func);
void hookSignalCall(QQmlEngine_ *engine, GoRef func, DataValue *params);
void hookSignalDisconnect(GoRef func);
void hookPanic(char *message);
int hookListPropertyCount(GoRef ref, intptr_t reflectIndex, intptr_t setIndex);
QObject_ *hookListPropertyAt(GoRef ref, intptr_t reflectIndex, intptr_t setIndex, int i);
Expand Down
4 changes: 2 additions & 2 deletions cpp/connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Connector : public QObject

public:

Connector(QObject *sender, QMetaMethod method, QQmlEngine *engine, void *func, int argsLen)
Connector(QObject *sender, QMetaMethod method, QQmlEngine *engine, GoRef func, int argsLen)
: QObject(sender), engine(engine), method(method), func(func), argsLen(argsLen) {};

virtual ~Connector();
Expand All @@ -27,7 +27,7 @@ class Connector : public QObject

QQmlEngine *engine;
QMetaMethod method;
void *func;
GoRef func;
int argsLen;
};

Expand Down
12 changes: 6 additions & 6 deletions cpp/govaluetype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
#define DEFINE_GOVALUETYPE(N) \
template<> QMetaObject GoValueType<N>::staticMetaObject = QMetaObject(); \
template<> GoTypeInfo *GoValueType<N>::typeInfo = 0; \
template<> GoTypeSpec_ *GoValueType<N>::typeSpec = 0;
template<> GoTypeSpec_ GoValueType<N>::typeSpec = 0;

#define DEFINE_GOPAINTEDVALUETYPE(N) \
template<> QMetaObject GoPaintedValueType<N>::staticMetaObject = QMetaObject(); \
template<> GoTypeInfo *GoPaintedValueType<N>::typeInfo = 0; \
template<> GoTypeSpec_ *GoPaintedValueType<N>::typeSpec = 0;
template<> GoTypeSpec_ GoPaintedValueType<N>::typeSpec = 0;

DEFINE_GOVALUETYPE(1)
DEFINE_GOVALUETYPE(2)
Expand Down Expand Up @@ -76,7 +76,7 @@ static int goValueTypeN = 0;
static int goPaintedValueTypeN = 0;

template<int N>
int registerSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec) {
int registerSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) {
GoValueType<N>::init(info, spec);
return qmlRegisterSingletonType< GoValueType<N> >(location, major, minor, name, [](QQmlEngine *qmlEngine, QJSEngine *jsEngine) -> QObject* {
QObject *singleton = new GoValueType<N>();
Expand All @@ -86,7 +86,7 @@ int registerSingletonN(char *location, int major, int minor, char *name, GoTypeI
}

template<int N>
int registerPaintedSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec) {
int registerPaintedSingletonN(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec) {
GoPaintedValueType<N>::init(info, spec);
return qmlRegisterSingletonType< GoPaintedValueType<N> >(location, major, minor, name, [](QQmlEngine *qmlEngine, QJSEngine *jsEngine) -> QObject* {
QObject *singleton = new GoPaintedValueType<N>();
Expand All @@ -100,7 +100,7 @@ int registerPaintedSingletonN(char *location, int major, int minor, char *name,
#define GOPAINTEDVALUETYPE_CASE_SINGLETON(N) \
case N: return registerPaintedSingletonN<N>(location, major, minor, name, info, spec);

int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec)
int registerSingleton(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec)
{
if (!info->paint) {
switch (++goValueTypeN) {
Expand Down Expand Up @@ -178,7 +178,7 @@ int registerSingleton(char *location, int major, int minor, char *name, GoTypeIn
#define GOPAINTEDVALUETYPE_CASE(N) \
case N: GoPaintedValueType<N>::init(info, spec); return qmlRegisterType< GoPaintedValueType<N> >(location, major, minor, name);

int registerType(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ *spec)
int registerType(char *location, int major, int minor, char *name, GoTypeInfo *info, GoTypeSpec_ spec)
{
if (!info->paint) {
switch (++goValueTypeN) {
Expand Down
8 changes: 4 additions & 4 deletions cpp/govaluetype.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ class GoValueType : public GoValue
GoValueType()
: GoValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {};

static void init(GoTypeInfo *info, GoTypeSpec_ *spec)
static void init(GoTypeInfo *info, GoTypeSpec_ spec)
{
typeInfo = info;
typeSpec = spec;
static_cast<QMetaObject &>(staticMetaObject) = *metaObjectFor(typeInfo);
};

static GoTypeSpec_ *typeSpec;
static GoTypeSpec_ typeSpec;
static GoTypeInfo *typeInfo;
static QMetaObject staticMetaObject;
};
Expand All @@ -31,14 +31,14 @@ class GoPaintedValueType : public GoPaintedValue
GoPaintedValueType()
: GoPaintedValue(hookGoValueTypeNew(this, typeSpec), typeInfo, 0) {};

static void init(GoTypeInfo *info, GoTypeSpec_ *spec)
static void init(GoTypeInfo *info, GoTypeSpec_ spec)
{
typeInfo = info;
typeSpec = spec;
static_cast<QMetaObject &>(staticMetaObject) = *metaObjectFor(typeInfo);
};

static GoTypeSpec_ *typeSpec;
static GoTypeSpec_ typeSpec;
static GoTypeInfo *typeInfo;
static QMetaObject staticMetaObject;
};
Expand Down
2 changes: 1 addition & 1 deletion datatype.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func unpackDataValue(dvalue *C.DataValue, engine *Engine) interface{} {
case C.DTGoAddr:
// ObjectByName also does this fold conversion, to have access
// to the cvalue. Perhaps the fold should be returned.
fold := ensureEngine(engine.addr, uintptr(datap))
fold := ensureEngine(engine.addr, C.GoRef(uintptr(datap)))
return fold.gvalue
case C.DTInvalid:
return nil
Expand Down
Loading