filcuc / dotherside

C language library for creating bindings for the Qt QML language
Other
200 stars 40 forks source link

feat: add signal handler for status-go #84

Closed richard-ramos closed 4 years ago

richard-ramos commented 4 years ago

Oops! I opened this PR by mistake

filcuc commented 4 years ago

Can you explain your use case?

richard-ramos commented 4 years ago

Sure!

TLDR: I want to invoke a QObject slot proc from a non-qt thread

We are currently working on a desktop client for status.im, with nim+NimQML for the frontend, and a go library exported as a static library for the backend. This library has a function that receives a callback. It also has an event loop where this callback is executed, passing as arguments json strings (we call them 'signals'). On this callback is where we receive the chat messages.

For reference, here's the binding used for that function:

type SignalCallback* = proc(eventMessage: cstring): void {.cdecl.}

proc setSignalEventCallback*(callback: SignalCallback) {.importc: "SetSignalEventCallback".}

Originally I attempted to call the slot function of a QObject directly inside the callback I pass to setSignalEventCallback, but I ended up with some SIGSEGV: Illegal storage access. (Attempt to read from nil?). So, after some research, I found out that since the callback is executed in a non-qt thread, invokeMethod seemed like the way to go to achieve cross-event-loop communication, and I ended up adding a new function in DOtherside and NimQML:

https://github.com/status-im/dotherside/blob/master/lib/src/DOtherSide.cpp#L721-L725

https://github.com/status-im/nimqml/blob/master/src/nimqml.nim#L33-L36

This function is then invoked here and we end up receiven the signals successfully. https://github.com/status-im/nim-status-client/blob/5ca1cfbe198272bb97e5a501f76272941c9c7461/src/nim_status_client.nim#L85-L88

Of course, this is still a WIP. I want to create a cpp library where this dos_signal will live, and a nim package for the nim->c bindings instead of adding these functions inside DOtherSide and NimQML. (I'm still struggling in how to do that due to lack of experience in both C++ and Nim).

Another thing I want to improve is removing the need of having the QObject as a global variable like I do here: https://github.com/status-im/nim-status-client/blob/signal-handling/src/nim_status_client.nim#L27-L29 because having the callback being declared with the {.cdecl.} pragma causes nim to complain: illegal capture 'logicQObjPointer' because ':anonymous' has the calling convention: <cdecl>