Dart/Flutter ffi(外来函数接口)原生回调,例如:sqlite3_exec

Ala*_*laq 8 ffi dart flutter dart-ffi

您好,我正在使用 dart:ffi 与我的本机 c/c++ 库构建一个接口。我需要一种方法来获取从 c 到 dart 的回调,例如在 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 */
);
Run Code Online (Sandbox Code Playgroud)

in 的第三个参数sqlite3_exec是指向回调的函数指针。所以如果我在 dart 中使用调用这个函数,ffi我需要传递一个函数指针:在dart:ffi Pointer类中有一个名为fromFunctionwitch的函数接受一个 dart 静态函数和一个exceptionalReturn; 但是仅仅通过调用这个函数来获取一个 dart 托管函数的函数指针:a(sigterm)被引发并且 dart 代码不再在这个过程中工作。

所以我的问题:有没有办法在 dart 中获得本机回调,如在 Python、c#、..

额外:有什么方法可以包含dartinoflutter项目中,因为这个ForeignDartFunction涵盖了我需要的东西。

Ric*_*eap 18

我有一个例子可以工作。希望你能适应你的情况。

示例 C 函数

EXTERNC int32_t foo(
                    int32_t bar,
                    int32_t (*callback)(void*, int32_t)
                    ) {
    return callback(nullptr, bar);
}
Run Code Online (Sandbox Code Playgroud)

飞镖代码

首先是typedefs. 我们需要两个用于本机函数foo,一个用于 Dart 回调。

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);
Run Code Online (Sandbox Code Playgroud)

和回调的代码

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

和查找

  ExampleFoo nativeFoo =
    nativeLib.lookup<NativeFunction<example_foo>>('foo').asFunction();
Run Code Online (Sandbox Code Playgroud)

最后,像这样使用它:

  int foo(int i) {
    return nativeFoo(
      i,
      Pointer.fromFunction<example_callback>(callback, except),
    );
  }
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,foo(123)打印flutter: in callback i=123并返回124

  • 应该注意的是,这仅适用于 Dart 创建的线程,因此同步调用、异步回调等。如果 Sqlite 在创建的 Sqlite 线程上进行回调,则 **不会** 工作,因为它破坏了 Darts 线程并发安全模型,该模型在以下位置进行跟踪:https://github.com/dart-lang/sdk/issues/37022。 (5认同)
  • 是的,我也应该展示这一点。`静态常量除了 = -1;` (2认同)