Dart/Flutter ffi(外部函数接口)本机回调,例如:sqlite3_exec
Posted
技术标签:
【中文标题】Dart/Flutter ffi(外部函数接口)本机回调,例如:sqlite3_exec【英文标题】:Dart/Flutter ffi (Foreign Function Interface) native callbacks eg: sqlite3_exec 【发布时间】:2020-08-15 21:01:53 【问题描述】:您好,我正在使用 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 */
);
sqlite3_exec
中的第三个参数是指向回调的函数指针。
所以如果我使用ffi
在dart中调用这个函数,我需要传递一个函数指针:在dart:ffi
Pointer
类中有一个名为fromFunction
的函数,女巫接受一个dart静态函数和一个exceptionalReturn
;但只需调用此函数即可获取 dart 托管函数的函数指针:引发 (sigterm)
并且 dart 代码在此过程中不再起作用。
所以我的问题:有什么方法可以在 dart 中获得本机回调,如 Python、c#、..
额外:
有什么办法可以将dartino
包含在flutter
项目中,因为这个ForeignDartFunction 满足了我的需要。
【问题讨论】:
你看过Pointer.fromFunction
吗? api.dart.dev/stable/2.8.1/dart-ffi/Pointer/fromFunction.html
@julemand101 是的,我做到了,我的问题暗示了这一点,文档没有fromFunction
的示例。
啊抱歉,没看过那部分。
你确定回调是在主线程上进行的,而不是在库中创建的。
@RichardHeap 我没有调用该函数,只是在 dart 中获取回调函数指针,在调用“Pointer.fromFunction”时引发“sigterm”
【参考方案1】:
我有一个例子可以工作。希望您可以根据自己的情况进行调整。
示例 C 函数
EXTERNC int32_t foo(
int32_t bar,
int32_t (*callback)(void*, int32_t)
)
return callback(nullptr, bar);
飞镖代码
首先是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);
以及回调的代码
static int callback(Pointer<Void> ptr, int i)
print('in callback i=$i');
return i + 1;
和查找
ExampleFoo nativeFoo =
nativeLib.lookup<NativeFunction<example_foo>>('foo').asFunction();
最后,像这样使用它:
int foo(int i)
return nativeFoo(
i,
Pointer.fromFunction<example_callback>(callback, except),
);
正如预期的那样,foo(123)
打印 flutter: in callback i=123
并返回 124
【讨论】:
谢谢,我已经有一个工作示例,我会将其标记为正确答案,因为它涵盖了所需的所有内容。 是的,我也应该证明这一点。static const except = -1;
我的问题是fromFunction
中的第二个参数exceptionalReturn
,dart 要求它是一个常量值,显然 -5(和负值)不是 dart 编译器的常量值/翻译。所以我需要问你,将值存储在名为except
的变量中是否正常工作。
需要注意的是,这只适用于 Dart 创建的线程,所以同步调用,异步回调,即。如果 Sqlite 在线程上执行回调,则创建的 Sqlite 将 NOT 工作,因为它会破坏 Darts 线程并发安全模型,该模型在以下位置进行跟踪:github.com/dart-lang/sdk/issues/37022。以上是关于Dart/Flutter ffi(外部函数接口)本机回调,例如:sqlite3_exec的主要内容,如果未能解决你的问题,请参考以下文章