Dart/Flutter ffi (Foreign Function Interface) native callbacks eg: sqlite3_exec
Asked Answered
B

1

14

Hello I am using dart:ffi to build an interface with my native c/c++ library. and I needed a way to get a callback from c to dart as an example in sqlite:

int sqlite3_exec(
    sqlite3*,                                  /* An open database */
    const char *sql,                           /* SQL to be evaluated */
    int (*callback)(void*,int,char**,char**),  /* Callback function */
    void *,                                    /* 1st argument to callback */
    char **errmsg                              /* Error msg written here */
);

the third parameter in sqlite3_exec is function pointer to a callback. so if I called this function in dart using ffi I need to pass a function pointer: and in dart:ffi Pointer class there is a function named fromFunction witch accepts a dart static function and an exceptionalReturn; but just by calling this function to get the function pointer of a dart managed function: a (sigterm) is raised and the dart code no long work in the process.

So My Question: Is there any way to get a native callback in dart, as in Python, c#, ..

Extra: Is there any way to include dartino in a flutter project, since this ForeignDartFunction covers what I need.

Ballesteros answered 1/5, 2020 at 11:12 Comment(5)
Have you looked at Pointer.fromFunction? api.dart.dev/stable/2.8.1/dart-ffi/Pointer/fromFunction.htmlFullback
@Fullback Yes I did, it is implied by my question, the documentation has no example for fromFunction.Stooge
Ah sorry, did not read that part.Fullback
Are you sure that the callback is being made on the main thread, and not one created in the library.Wattmeter
@RichardHeap I did not get to call the function, just getting the callback function pointer in dart raised ‘sigterm’ when called ‘Pointer.fromFunction’Stooge
W
32

I got an example to work. Hopefully you can adapt this to your case.

Example C function

EXTERNC int32_t foo(
                    int32_t bar,
                    int32_t (*callback)(void*, int32_t)
                    ) {
    return callback(nullptr, bar);
}

Dart code

First the typedefs. We need two for the native function foo and one for the Dart callback.

typedef example_foo = Int32 Function(
    Int32 bar, Pointer<NativeFunction<example_callback>>);
typedef ExampleFoo = int Function(
    int bar, Pointer<NativeFunction<example_callback>>);

typedef example_callback = Int32 Function(Pointer<Void>, Int32);

and the code for the callback

  static int callback(Pointer<Void> ptr, int i) {
    print('in callback i=$i');
    return i + 1;
  }

and the lookup

  ExampleFoo nativeFoo =
    nativeLib.lookup<NativeFunction<example_foo>>('foo').asFunction();

and, finally, use it like this:

  int foo(int i) {
    return nativeFoo(
      i,
      Pointer.fromFunction<example_callback>(callback, except),
    );
  }

as expected, foo(123) prints flutter: in callback i=123 and returns 124

Wattmeter answered 1/5, 2020 at 21:16 Comment(6)
thank you, I already had a working example,I will mark this as a correct answer since it covers every thing needed.Stooge
Yes, I should have shown that too. static const except = -1;Wattmeter
my issue was with the 2nd parameter exceptionalReturn in fromFunction, dart requires it to be a constant value, and apparently -5 (and negative value) is not a constant value for the dart compiler /interpreter. So I need to ask you did it work correctly having the value stored in a variable named except.Stooge
It should be noted that this will only work for a Dart created thread, so sync calls, async callbacks, ie. if theSqlite does the callback on a thread Sqlite created will NOT work as its breaks Darts threading-concurrency safety model, which is tracked in: github.com/dart-lang/sdk/issues/37022.Meow
@RichardHeap If so, is it possible to receive 124, the retrun value of dart, when calling foo from main in C?Delative
No - as in the comment above, you can only call from C to Dart if that C function is itself being called from Dart.Wattmeter

© 2022 - 2024 — McMap. All rights reserved.