FFI and callbacks from C to Dart

1,138 views
Skip to first unread message

Mark Lee

unread,
May 7, 2020, 3:44:22 PM5/7/20
to Dart Misc
I've just started learning Dart and for the project I had in mind it would rely heavily on using FFI to interoperate with a third party "C" library.

One of the key things I need to do is to register a callback with that native library and have that library asynchronously send events back to my Dart code.

For a proof of concept I do actually have at least the setup for that working - I know that the native callback is registered correctly, I know that it tries to callback into my Dart code, but my problem is that these events are coming in via some thread created by the native library and as expected under these circumstances I get the "cannot invoke native callback outside an isolate" error - I understand why that happens - my question is can anything be done about it.

Researching this led me to not too much in all honestly, I found some samples showing the use of NativePort to send messages from the native side so they were consumed by the proper thread on the Dart side but I can't see how I could use that.

The problem is that I have no control over that native library, I can't make changes to or write things like wrapper functions, I don't really want to write any new native code at all I just want to write Dart code.

Is there any viable solution for this or am I stuck?

I must admit I've been learning Dart for about one day total so I don't have a deep understanding of this yet.

John Ryan

unread,
May 7, 2020, 5:19:23 PM5/7/20
to Dart Misc, Mark Lee
Hi Mark,

Can you take a look at this thread, specifically this comment? I haven't run into this issue, but they appear similar.

Thanks,

Mark Lee

unread,
May 11, 2020, 4:08:56 AM5/11/20
to Dart Misc, wm.ma...@gmail.com
Hi,

I did already find that thread and associated sample code.


When it registers the callback with the native code it passes a port:

final interactiveCppRequests = ReceivePort()..listen(requestExecuteCallback);
final int nativePort = interactiveCppRequests.sendPort.nativePort;
registerCallback1(nativePort, callback1FP);
registerCallback2(nativePort, callback2FP);

The register callback native code in that sample looks like this:

DART_EXPORT void RegisterMyCallbackNonBlocking(Dart_Port send_port,
                                               void (*callback)(intptr_t)) {
  my_callback_non_blocking_fp_ = callback;
  my_callback_non_blocking_send_port_ = send_port;
}

And then later this native code uses that send_port to send messages back to the Dart code.

So essentially it seems the native library needs to know about Dart, which is not possible for my use-case. I can not change the native library, and writing an "extra" native layer to make this work is not something I really wanted to do.

This is the nub of what I'm asking I suppose, is the only way to make this work to write more native code.

Thanks.
Reply all
Reply to author
Forward
0 new messages