From ceab71c3a933952e4223830f727f0ba4f67d1b2c Mon Sep 17 00:00:00 2001 From: Gustavo Niemeyer Date: Thu, 12 Sep 2013 17:20:34 -0300 Subject: [PATCH] Go gets the result from calling QML methods. --- all_test.go | 4 ++-- cpp/capi.cpp | 5 +++-- cpp/capi.h | 2 +- datatype.go | 3 +++ qml.go | 9 ++++++--- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/all_test.go b/all_test.go index 2e3e273f..9f45ac63 100644 --- a/all_test.go +++ b/all_test.go @@ -415,8 +415,8 @@ var tests = []struct { }, { Summary: "Call a QML method from Go", - QML: `Item { function f() { console.log("f was called") } }`, - Done: func(d *TestData) { d.compinst.Call("f") }, + QML: `Item { function f() { console.log("f was called"); return ""; } }`, + Done: func(d *TestData) { d.Check(d.compinst.Call("f"), Equals, "") }, DoneLog: "f was called", }, } diff --git a/cpp/capi.cpp b/cpp/capi.cpp index 9f47e3c5..63d31403 100644 --- a/cpp/capi.cpp +++ b/cpp/capi.cpp @@ -204,13 +204,14 @@ void objectGetProperty(QObject_ *object, const char *name, DataValue *value) packDataValue(&var, value); } -void objectInvoke(QObject_ *object, const char *method) +void objectInvoke(QObject_ *object, const char *method, DataValue *resultdv) { QObject *qobject = reinterpret_cast(object); - // TODO Support parameters and result. + // TODO Parameter support. QVariant result; QMetaObject::invokeMethod(qobject, method, Qt::DirectConnection, Q_RETURN_ARG(QVariant, result)); + packDataValue(&result, resultdv); } void objectSetParent(QObject_ *object, QObject_ *parent) diff --git a/cpp/capi.h b/cpp/capi.h index 71286c8b..9f1f1541 100644 --- a/cpp/capi.h +++ b/cpp/capi.h @@ -107,7 +107,7 @@ void contextSetObject(QQmlContext_ *context, QObject_ *value); void delObject(QObject_ *object); void objectGetProperty(QObject_ *object, const char *name, DataValue *value); void objectSetParent(QObject_ *object, QObject_ *parent); -void objectInvoke(QObject_ *object, const char *method); +void objectInvoke(QObject_ *object, const char *method, DataValue *result); QQmlComponent_ *newComponent(QQmlEngine_ *engine, QObject_ *parent); void componentSetData(QQmlComponent_ *component, const char *data, int dataLen, const char *url, int urlLen); diff --git a/datatype.go b/datatype.go index acae6990..47ad3f8b 100644 --- a/datatype.go +++ b/datatype.go @@ -89,6 +89,9 @@ func packDataValue(value interface{}, dvalue *C.DataValue, engine *Engine, owner } // unpackDataValue converts a value shipped by C++ into a native Go value. +// +// HEADS UP: This is considered safe to be run out of the main GUI thread. +// If that changes, fix the call sites. func unpackDataValue(dvalue *C.DataValue) interface{} { datap := unsafe.Pointer(&dvalue.data) switch dvalue.dataType { diff --git a/qml.go b/qml.go index 93435e1e..7af4232e 100644 --- a/qml.go +++ b/qml.go @@ -285,14 +285,17 @@ func (o *commonObject) Field(name string) interface{} { return unpackDataValue(&value) } -func (o *commonObject) Call(method string) { - // TODO Support parameters and result. +func (o *commonObject) Call(method string) interface{} { + // TODO Parameter support. + // TODO What about errors? + var result C.DataValue gui(func() { // TODO Do not allocate this string every time. name := C.CString(method) defer C.free(unsafe.Pointer(name)) - C.objectInvoke(o.addr, name) + C.objectInvoke(o.addr, name, &result) }) + return unpackDataValue(&result) } // Destroy finalizes the value and releases any resources used.