这篇文章是Github Issue here的副本。dart --version
Dart SDK版本:2.15.0-116.0.dev(dev)(Thu Sep 16 09:47:01 2021 -0700)on“linux_x64”
我一直在寻找examples的回调,我试图让回调为我在FFI工作。
我的现状
我的库中有一个函数,它需要一个指向函数的指针。ffigen
生成的绑定对我来说似乎是正确的。
int SetCallback(
CallbackType callback,
) {
return _SetCallback(
callback,
);
}
late final _SetCallbackPtr =
_lookup<NativeFunction<Int32 Function(CallbackType)>>(
'SetCallback');
late final _SetCallback =
_SetCallbackPtr.asFunction<int Function(CallbackType)>();
字符串
其中,typedef CallbackType = Pointer<NativeFunction<Void Function(Uint32)>>;
。
我想在这里做的是在Dart中设置这个回调函数,将其传递给FFI,本质上将其用作我在C中的回调函数。在我的API中,它从FFI代码中抽象出来(这意味着我有一个充满静态函数的类MyLibrary,用户将直接调用这些静态函数,然后从我创建的类MyNativeLibrary的object _nativeLibrary调用函数),我有:
static int SetCallback({required CallbackFuncDart callback}) {
Pointer<NativeFunction<CallbackFunc>> pointer = Pointer.fromFunction(callback);
int status = _nativeLibrary.SetCallback(
pointer,
);
if (STATUS_OK != status) {
throw LibLexemeException(status);
}
return status;
}
typedef CallbackFunc = Void Function(Uint32);
typedef CallbackFuncDart = void Function(int);
型
虽然the sqlite ffi example在这里指出,
dart:ffi尚不支持的功能:
Callbacks from C back into Dart.
型
我相信文档还没有更新以反映the samples here.的变化。示例还不是很清楚,因为它们没有任何C/C++文件,或者C函数是如何工作的。即便如此,我认为this example包含一个段(最后一个代码块)其中一个Dart函数被作为回调传递,我已经在我的程序中复制了它。我不清楚这将如何工作,但在尝试编译我的我得到的程序:
ERROR: ../lib/library_lexeme.dart:180:74: Error: fromFunction expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code. Closures and tear-offs are not supported because they can capture context.
ERROR: Pointer<NativeFunction<CallbackFunc>> pointer = Pointer.fromFunction(callback);
型
3条答案
按热度按时间1zmg4dgp1#
简单来说,你不能把回调作为参数传递:
字符串
这很烦人,但你必须使用一个预先定义的静态函数,以便从C调用dart回调。
envsm3lx2#
显然,目前只有静态函数可以通过ffi传递。但是如果你必须访问一个示例的数据,并且你确定该示例存在,你可以使用我的解决方案。我对示例使用静态列表。这是愚蠢和丑陋的,但它对我有效:
字符串
为了清晰起见,我省略了必要的c代码、FFIMap和类型转换,因此它显然不会像这样编译。
mxg2im7a3#
使用Dart 3.2,您现在可以从任何Dart函数或闭包创建回调,扩展到静态或顶级函数之外。
目前有两种方法可以实现这一点:
***NativeCallable.isolateLocal:**这构造了一个
NativeCallable
,必须从创建它的 * 同一个 * 线程调用。它构建在Pointer.fromFunction提供的功能之上,仅限于从静态或顶级函数创建函数指针。***NativeCallable.listener:**这将构造一个可以从 * 任何 * 线程调用的
NativeCallable
。此功能在Dart 3.1中引入,仅支持void
函数。下面是示例的修改版本,现在包含了
NativeCallable.isolateLocal
:字符串