如何将const char*传递给Dart?调用asFunction()时出现类型错误
报错根因
asFunction() 报类型匹配错误是因为你写的C侧原生函数签名不符合FFI规范,存在两个问题:
NativeFunction要求泛型参数里的所有类型必须是dart:ffi提供的C原生类型,不能直接用Dart的int类型,C语言的int对应原生类型Int32Pointer<Utf8>是package:ffi提供的Dart层字符串编解码封装类型,不属于原生类型,C侧的const char*在原生签名里对应的类型是Pointer<Char>
修正后可运行代码
import 'dart:ffi'; import 'dart:io' show Directory; import 'package:path/path.dart' as path; import 'package:ffi/ffi.dart'; // C侧原生函数签名,全部使用ffi提供的原生类型 // 对应C函数:void td_send(int client_id, const char *request) typedef C_td_send = Void Function(Int32 client_id, Pointer<Char> request); // Dart侧调用签名,使用Dart常规类型 typedef TdSend = void Function(int client_id, Pointer<Utf8> request); void main(List<String> arguments) async { final libraryPath = path.join(Directory.current.path, '/usr/local/lib/', 'libtdjson.so'); final dylib = DynamicLibrary.open(libraryPath); final TdSend tdRequest = dylib .lookup<NativeFunction<C_td_send>>('td_send') .asFunction<TdSend>(); // 调用示例:Dart字符串转C侧兼容的Utf8格式char* final request = '{"@type": "getAuthorizationState"}'.toNativeUtf8(); tdRequest(0, request); // 手动释放native堆内存,避免泄漏 calloc.free(request); }
注意事项
- 如果TDLib的
client_id是64位整数,把C侧签名里的Int32替换成Int64即可,Dart侧参数依然保留int类型,FFI会自动完成数值转换 Pointer<Utf8>本质是Pointer<Char>的子类,所以可以直接传给匹配Pointer<Char>的C函数参数,不需要额外强转- 所有通过
toNativeUtf8()、calloc、malloc申请的原生内存,必须在使用完成后手动释放,否则会造成持续内存泄漏
内容的提问来源于stack exchange,提问作者ghost239
相关产品推荐
相关产品推荐

