You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将const char*传递给Dart?调用asFunction()时出现类型错误

报错根因

asFunction() 报类型匹配错误是因为你写的C侧原生函数签名不符合FFI规范,存在两个问题:

  • NativeFunction 要求泛型参数里的所有类型必须是dart:ffi提供的C原生类型,不能直接用Dart的int类型,C语言的int对应原生类型Int32
  • Pointer<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:24:23