From d229da9102a2025d15e65321f20d58a0d21a6425 Mon Sep 17 00:00:00 2001 From: Filippo Cucchetto Date: Mon, 8 Dec 2014 12:55:09 +0100 Subject: [PATCH] Implemented the slot callback in Nim --- DOtherSide/DOtherSide/DOtherSide.cpp | 14 +- DOtherSide/DOtherSide/DOtherSide.h | 3 +- DOtherSide/DynamicQObject/DynamicSlot.cpp | 2 +- Nim/NimQml.nim | 187 ++++++++++++++++++++++ Nim/NimQmlTypes.nim | 11 ++ Nim/main.nim | 133 ++------------- Nim/main.qml | 5 +- 7 files changed, 229 insertions(+), 126 deletions(-) create mode 100644 Nim/NimQml.nim create mode 100644 Nim/NimQmlTypes.nim diff --git a/DOtherSide/DOtherSide/DOtherSide.cpp b/DOtherSide/DOtherSide/DOtherSide.cpp index c40ec9d..44a9403 100644 --- a/DOtherSide/DOtherSide/DOtherSide.cpp +++ b/DOtherSide/DOtherSide/DOtherSide.cpp @@ -45,6 +45,13 @@ void dos_qqmlapplicationengine_load(void *vptr, const char *filename) engine->load(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QDir::separator() + QString(filename))); } +void dos_qqmlapplicationengine_context(void* vptr, void** context) +{ + QQmlApplicationEngine* engine = reinterpret_cast(vptr); + engine->rootContext(); + *context = engine->rootContext(); +} + void dos_qqmlapplicationengine_delete(void* vptr) { QQmlApplicationEngine* engine = reinterpret_cast(vptr); @@ -100,7 +107,7 @@ void dos_chararray_create(CharPtr& ptr, int size) ptr = 0; } -void dos_chararray_delete(CharPtr &ptr) +void dos_chararray_delete(CharPtr ptr) { if (ptr) delete[] ptr; } @@ -195,10 +202,10 @@ void dos_qvariant_setString(void* vptr, const char* value) *variant = value; } - void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObjectCallback) { auto dynamicQObject = new DynamicQObject(); + QQmlEngine::setObjectOwnership(dynamicQObject, QQmlEngine::CppOwnership); dynamicQObject->setDObjectPointer(dObjectPointer); dynamicQObject->setDObjectCallback(dObjectCallback); *vptr = dynamicQObject; @@ -207,6 +214,7 @@ void dos_qobject_create(void** vptr, void* dObjectPointer, DObjectCallback dObje void dos_qobject_delete(void *vptr) { auto dynamicQObject = reinterpret_cast(vptr); + dynamicQObject->disconnect(); delete dynamicQObject; } @@ -237,8 +245,6 @@ void dos_qobject_signal_create(void* vptr, const char* name, int parametersCount argumentsTypes << static_cast(parametersMetaTypes[i]); dynamicQObject->registerSignal(QString::fromStdString(name), argumentsTypes, *signalIndex); - - qDebug() << "C++: registered the" << name << "signal"; } void dos_qobject_signal_emit(void* vptr, const char* name, int parametersCount, void** parameters) diff --git a/DOtherSide/DOtherSide/DOtherSide.h b/DOtherSide/DOtherSide/DOtherSide.h index 415a555..5f80675 100644 --- a/DOtherSide/DOtherSide/DOtherSide.h +++ b/DOtherSide/DOtherSide/DOtherSide.h @@ -16,6 +16,7 @@ void dos_qguiapplication_delete(); void dos_qqmlapplicationengine_create(void** vptr); void dos_qqmlapplicationengine_load(void* vptr, const char* filename); +void dos_qqmlapplicationengine_context(void* vptr, void** context); void dos_qqmlapplicationengine_delete(void* vptr); void dos_qquickview_create(void** vptr); @@ -29,7 +30,7 @@ void dos_qqmlcontext_baseUrl(void* vptr, CharPtr& result, int& length); void dos_qqmlcontext_setcontextproperty(void* vptr, const char* name, void* value); void dos_chararray_create(CharPtr& ptr, int size); -void dos_chararray_delete(CharPtr& ptr); +void dos_chararray_delete(CharPtr ptr); void dos_qvariant_create(void **vptr); void dos_qvariant_create_int(void **vptr, int value); diff --git a/DOtherSide/DynamicQObject/DynamicSlot.cpp b/DOtherSide/DynamicQObject/DynamicSlot.cpp index 2510d5a..79d060e 100644 --- a/DOtherSide/DynamicQObject/DynamicSlot.cpp +++ b/DOtherSide/DynamicQObject/DynamicSlot.cpp @@ -92,5 +92,5 @@ void DynamicSlot::_initSignature() d->signature = signature.arg(d->name, arguments).toUtf8(); - qDebug() << "C++ slot signature is " << d->signature; + qDebug() << "C++: slot signature is " << d->signature; } diff --git a/Nim/NimQml.nim b/Nim/NimQml.nim new file mode 100644 index 0000000..ca1b73d --- /dev/null +++ b/Nim/NimQml.nim @@ -0,0 +1,187 @@ +import NimQmlTypes +import tables + +export QObject +export QApplication +export QVariant +export QQmlApplicationEngine +export QQmlContext + +type QMetaType* {.pure.} = enum + UnknownType = cint(0), + Bool = cint(1), + Int = cint(2), + QString = cint(10), + VoidStar = cint(31), + QVariant = cint(41), + Void = cint(43) + +proc debugMsg(message: string) = + echo "NimQml: ", message + +proc debugMsg(typeName: string, procName: string) = + var message = typeName + message &= ": " + message &= procName + debugMsg(message) + +# QVariant +proc dos_qvariant_create(variant: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_int(variant: var pointer, value: cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_bool(variant: var pointer, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_string(variant: var pointer, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_create_qobject(variant: var pointer, value: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_delete(variant: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_isnull(variant: pointer, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toInt(variant: pointer, value: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toBool(variant: pointer, value: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qvariant_toString(variant: pointer, value: var cstring, length: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc create*(variant: var QVariant) = + var data: pointer + dos_qvariant_create(data) + variant = QVariant(data) + +proc create*(variant: var QVariant, value: cint) = + var data: pointer + dos_qvariant_create_int(data, value) + variant = QVariant(data) + +proc create*(variant: var QVariant, value: bool) = + var data: pointer + dos_qvariant_create_bool(data, value) + variant = QVariant(data) + +proc create*(variant: var QVariant, value: string) = + var data: pointer + dos_qvariant_create_string(data, value) + variant = QVariant(data) + +proc create*(variant: var QVariant, value: QObject) = + var data: pointer + dos_qvariant_create_qobject(data, value.data) + variant = QVariant(data) + +proc delete*(variant: QVariant) = + debugMsg("QVariant", "delete") + dos_qvariant_delete(pointer(variant)) + +proc isNull*(variant: QVariant): bool = + dos_qvariant_isnull(pointer(variant), result) + +proc toInt*(variant: QVariant): cint = + dos_qvariant_toInt(pointer(variant), result) + +proc toBool*(variant: QVariant): bool = + dos_qvariant_toBool(pointer(variant), result) + +proc toString*(variant: QVariant): string = + var rawCString: cstring + var rawCStringLength: cint + dos_qvariant_toString(pointer(variant), rawCString, rawCStringLength) + result = $rawCString + dos_chararray_delete(rawCString) + +# QQmlApplicationEngine +proc dos_qqmlapplicationengine_create(engine: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_load(engine: pointer, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_context(engine: pointer, context: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qqmlapplicationengine_delete(engine: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc create*(engine: var QQmlApplicationEngine) = + var temp: pointer + dos_qqmlapplicationengine_create(temp) + engine = QQmlApplicationEngine(temp) + +proc load*(engine: QQmlApplicationEngine, filename: cstring) = + dos_qqmlapplicationengine_load(pointer(engine), filename) + +proc rootContext*(engine: QQmlApplicationEngine): QQmlContext = + var context: pointer + dos_qqmlapplicationengine_context(pointer(engine), context) + result = cast[QQmlContext](context) + +proc delete*(engine: QQmlApplicationEngine) = + debugMsg("QQmlApplicationEngine", "delete") + dos_qqmlapplicationengine_delete(pointer(engine)) + +# QQmlContext +proc dos_qqmlcontext_setcontextproperty(context: pointer, propertyName: cstring, propertyValue: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc setContextProperty*(context: QQmlContext, propertyName: string, propertyValue: QVariant) = + dos_qqmlcontext_setcontextproperty(pointer(context), propertyName, pointer(propertyValue)) + +# QApplication +proc dos_qguiapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} +proc dos_qguiapplication_exec() {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qguiapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc create*(application: QApplication) = + debugMsg("QApplication", "create") + dos_qguiapplication_create() + +proc exec*(application: QApplication) = + debugMsg("QApplication", "exec") + dos_qguiapplication_exec() + +proc delete*(application: QApplication) = + debugMsg("QApplication", "delete") + dos_qguiapplication_delete() + +# QObject +type QVariantArray {.unchecked.} = array[0..0, QVariant] +type QVariantArrayPtr = ptr QVariantArray + +proc dos_qobject_create(qobject: var pointer, nimobject: pointer, qobjectCallback: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_delete(qobject: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qobject_slot_create(qobject: pointer, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc qobjectCallback(nimobject: pointer, slotName: QVariant, numArguments: cint, arguments: QVariantArrayPtr) {.exportc.} = + debugMsg("QObject", "qobjectCallback") + +proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] = + result = @[] + for metaType in metaTypes: + result.add(cint(metaType)) + +proc create*(qobject: var QObject) = + qobject.slots = initTable[string,cint]() + dos_qobject_create(qobject.data, addr(qobject), qobjectCallback) + +proc delete*(qobject: QObject) = + debugMsg("QObject", "delete") + dos_qobject_delete(qobject.data) + +proc registerSlot*(qobject: var QObject, slotName: string, metaTypes: openarray[QMetaType]) = + # Copy the metatypes array + var copy = toCIntSeq(metatypes) + var index: cint + dos_qobject_slot_create(qobject.data, slotName, cint(copy.len), cast[ptr cint](addr(copy[0])), index) + qobject.slots[slotName] = index + +# QQuickView +proc dos_qquickview_create(view: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_delete(view: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_show(view: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_source(view: pointer, filename: var cstring, length: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.} +proc dos_qquickview_set_source(view: pointer, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} + +proc create(view: var QQuickView) = + var temp: pointer + dos_qquickview_create(temp) + view = QQuickView(temp) + +proc source(view: QQuickView): cstring = + var length: int + dos_qquickview_source(pointer(view), result, length) + +proc `source=`(view: QQuickView, filename: cstring) = + dos_qquickview_set_source(pointer(view), filename) + +proc show(view: QQuickView) = + dos_qquickview_show(pointer(view)) + +proc delete(view: QQuickView) = + debugMsg("QQuickView", "delete") + dos_qquickview_delete(pointer(view)) \ No newline at end of file diff --git a/Nim/NimQmlTypes.nim b/Nim/NimQmlTypes.nim new file mode 100644 index 0000000..ca594b5 --- /dev/null +++ b/Nim/NimQmlTypes.nim @@ -0,0 +1,11 @@ +import tables + +type + QVariant* = distinct pointer + QQmlApplicationEngine* = distinct pointer + QQmlContext* = distinct pointer + QApplication* = distinct pointer + QObject* {.inheritable.} = ref object of RootObj + data*: pointer + slots*: Table[string, cint] + QQuickView* = distinct pointer \ No newline at end of file diff --git a/Nim/main.nim b/Nim/main.nim index f9e7d99..3e8150c 100644 --- a/Nim/main.nim +++ b/Nim/main.nim @@ -1,131 +1,26 @@ -# QApplication -proc dos_qguiapplication_create() {.cdecl, dynlib: "libDOtherSide.so", importc.} -proc dos_qguiapplication_exec() {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qguiapplication_delete() {.cdecl, dynlib:"libDOtherSide.so", importc.} +import NimQml -type QApplication = distinct pointer +type MyQObject = object of QObject -proc create(application: QApplication) = - echo "QApplication: create" - dos_qguiapplication_create() - -proc exec(application: QApplication) = - echo "QApplication: exec" - dos_qguiapplication_exec() - -proc delete(application: QApplication) = - echo "QApplication: delete" - dos_qguiapplication_delete() - -# QQmlApplicationEngine -proc dos_qqmlapplicationengine_create(engine: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_load(engine: pointer, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qqmlapplicationengine_delete(engine: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} - -type QQmlApplicationEngine = distinct pointer - -proc create(engine: var QQmlApplicationEngine) = - var temp: pointer - dos_qqmlapplicationengine_create(temp) - engine = QQmlApplicationEngine(temp) - -proc load(engine: QQmlApplicationEngine, filename: cstring) = - dos_qqmlapplicationengine_load(pointer(engine), filename) - -proc delete(engine: QQmlApplicationEngine) = - dos_qqmlapplicationengine_delete(pointer(engine)) - -# QQuickView -proc dos_qquickview_create(view: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_delete(view: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_show(view: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_source(view: pointer, filename: var cstring, length: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qquickview_set_source(view: pointer, filename: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} - -type QQuickView = distinct pointer - -proc create(view: var QQuickView) = - echo "QQuickView: create" - var temp: pointer - dos_qquickview_create(temp) - view = QQuickView(temp) - -proc source(view: QQuickView): cstring = - var length: int - dos_qquickview_source(pointer(view), result, length) - return - -proc `source=`(view: QQuickView, filename: cstring) = - echo "QQuickView: source=" - dos_qquickview_set_source(pointer(view), filename) - -proc show(view: QQuickView) = - echo "QQuickView: show" - dos_qquickview_show(pointer(view)) - -proc delete(view: QQuickView) = - echo "QQuickView: delete" - dos_qquickview_delete(pointer(view)) - -# QVariant -proc dos_qvariant_create(variant: var pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_int(variant: var pointer, value: int) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_bool(variant: var pointer, value: bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_create_string(variant: var pointer, value: cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_delete(variant: pointer) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_isnull(variant: pointer, isNull: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toInt(variant: pointer, value: var int) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toBool(variant: pointer, value: var bool) {.cdecl, dynlib:"libDOtherSide.so", importc.} -proc dos_qvariant_toString(variant: pointer, value: var cstring) {.cdecl, dynlib:"libDOtherSide.so", importc.} - -type QVariant = distinct pointer - -proc create(variant: var QVariant) = - var data: pointer - dos_qvariant_create(data) - variant = QVariant(data) - -proc create(variant: var QVariant, value: int) = - var data: pointer - dos_qvariant_create_int(data, value) - variant = QVariant(data) - -proc create(variant: var QVariant, value: bool) = - var data: pointer - dos_qvariant_create_bool(data, value) - variant = QVariant(data) - -proc create(variant: var QVariant, value: cstring) = - var data: pointer - dos_qvariant_create_string(data, value) - variant = QVariant(data) - -proc delete(variant: QVariant) = - dos_qvariant_delete(pointer(variant)) - -proc isNull(variant: QVariant): bool = - dos_qvariant_isnull(pointer(variant), result) - -proc toInt(variant: QVariant): int = - dos_qvariant_toInt(pointer(variant), result) - -proc toBool(variant: QVariant): bool = - dos_qvariant_toBool(pointer(variant), result) - -proc toString(variant: QVariant): cstring = - dos_qvariant_toString(pointer(variant), result) - - - -block: +when isMainModule: var app: QApplication app.create() finally: app.delete() + + var myQObject = new(MyQObject) + myQObject.create() + finally: myQObject.delete() + myQObject.registerSlot("myVoidSlot", [QMetaType.Void, QMetaType.Int]) var engine: QQmlApplicationEngine engine.create() finally: engine.delete() - engine.load("main.qml") + var variant: QVariant + variant.create(myQObject) + finally: variant.delete() + var rootContext: QQmlContext = engine.rootContext() + rootContext.setContextProperty("myObject", variant) + engine.load("main.qml") app.exec() \ No newline at end of file diff --git a/Nim/main.qml b/Nim/main.qml index 8986e94..6991e5b 100644 --- a/Nim/main.qml +++ b/Nim/main.qml @@ -6,7 +6,10 @@ ApplicationWindow { width: 400 height: 300 - Component.onCompleted: visible = true + Component.onCompleted: { + visible = true + myObject.myVoidSlot(10) + } Button {