Dart ffi传入回调报错:dart:ffi仅支持从原生代码调用静态Dart函数
错误原因
Pointer.fromFunction() 只支持传入顶层函数、类静态函数,不支持闭包、实例方法、局部函数这类可能携带上下文的动态函数,你当前代码直接将用户传入的动态callback参数传给fromFunction,就会触发这个编译错误。
解决方法
你可以通过静态存储中转用户自定义回调的方式实现需求,具体修改如下:
- 先定义全局变量存储用户传入的回调,再单独写一个符合要求的顶层静态回调函数,专门用于传给FFI:
// 存储用户自定义的回调 CallbackFuncDart? _userCallback; // 顶层静态回调函数,无上下文,符合fromFunction的入参要求 void _staticCallback(int eventId) { _userCallback?.call(eventId); } typedef CallbackFunc = Void Function(Uint32); typedef CallbackFuncDart = void Function(int);
- 修改你的封装方法,先把用户传入的回调存入全局变量,再将静态函数转为指针传给底层:
static int SetCallback({required CallbackFuncDart callback}) { // 存储用户自定义回调 _userCallback = callback; // 传入静态函数生成指针 Pointer<NativeFunction<CallbackFunc>> pointer = Pointer.fromFunction(_staticCallback); int status = _nativeLibrary.SetCallback(pointer); if (STATUS_OK != status) { throw LibLexemeException(status); } return status; }
注意事项
- 你当前使用的Dart 2.15开发版已经支持C回调Dart能力,该特性从Dart 2.17版本开始正式稳定,建议升级到更高稳定版本避免已知兼容问题
- 上述方案默认是单回调场景,如果需要同时支持多个不同回调,可以用Map存储不同标识对应的用户回调,C侧触发回调时携带标识,Dart静态函数根据标识取出对应回调执行即可
- 生成的函数指针需要在C侧可能调用回调的全生命周期内被Dart侧持有,避免被GC回收导致野指针崩溃,建议将指针存为类静态属性或者全局变量,不要定义为方法内的局部变量
- 如果你的回调有返回值,需要给
fromFunction传入第二个参数作为异常触发时的默认返回值,避免FFI调用直接崩溃,例如返回值为int的写法为Pointer.fromFunction(func, 0)
内容的提问来源于stack exchange,提问作者azan-n
相关产品推荐
相关产品推荐

