[英]Debug C++ code from Dart package using dart::ffi
[英]Callbacks in Dart: dart:ffi only supports calling static Dart functions from native code
这篇文章是这里的 Github 问题的副本。
dart --version
Dart SDK 版本:2.15.0-116.0.dev (dev) (Thu Sep 16 09:47:01 2021 -0700) on "linux_x64"
我一直在寻找回调的例子,我试图让回调在 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 类的对象 _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);
虽然sqlite ffi 示例在这里指出
dart:ffi 尚不支持的功能:
Callbacks from C back into Dart.
我相信文档尚未更新以反映此处示例的更改。 由于样本没有任何 C/C++ 文件,或者不了解 C 函数的工作原理,因此这些样本还不是很清楚。 即便如此,我认为这个示例包含一个段(最后一个代码块),其中一个 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);
简短的版本是您不能将回调作为参数传递:
static int SetCallback({required CallbackFuncDart callback}) {
Pointer<NativeFunction<CallbackFunc>> pointer = Pointer.fromFunction(callback); // <-- this isn't considered a static function
这很烦人,但是您必须使用提前定义的静态函数才能从 C 调用您的 dart 回调。
显然目前只能通过 ffi 传递静态函数。 但是,如果您必须访问实例的数据并且您确定该实例存在,您可以使用我的解决方法。 我对实例使用静态列表。 这既愚蠢又丑陋,但对我有用:
class CallbackClass {
static Int8 classCallback(int id) {
final instance = instanceList[id];
return instance.instanceCallback();
}
Int8 instanceCallback() { return instanceId; }
static List<CallbackClass> instanceList = <CallbackClass>[];
late final int instanceId;
CallbackClass {
instanceId = instanceList.length;
instanceList.insert(instanceId, this);
myFFImapping.passCallback(instanceId, Pointer.fromFunction<>(classCallback);)
}
}
为了清楚起见,我省略了必要的 c 代码、FFI 映射和强制转换以纠正类型,所以它显然不会像这样编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.