如何在Dart中通过FFI向C函数传递argv[]参数?
解决Dart FFI调用C函数时构造
argv的问题 你当前的思路误解了C语言中argv的结构——它不是一个包含多个空字符的单一字符串,而是一个指针数组:每个元素指向一个以null结尾的独立字符串,最后一个元素是NULL指针用来标记数组结束。Dart字符串确实无法包含空字符,所以我们需要换一种方式来构造符合C规范的argv。
正确构造C风格argv的步骤
- 先把所有命令行参数整理成Dart字符串列表,对应C里每个独立的
argv元素 - 将每个字符串转换为
Pointer<Utf8>(Dart FFI提供的UTF-8编码指针,自带null结尾) - 创建一个指针数组(
Pointer<Pointer<Utf8>>),长度为参数数量+1(最后补NULL) - 把每个
Pointer<Utf8>赋值到数组对应的位置,最后一个位置设为nullptr - 调用C函数时传入参数数量和这个指针数组,用完后记得释放所有分配的内存,避免泄漏
修正后的完整代码
import 'dart:ffi'; import 'dart:io'; import 'package:ffi/ffi.dart'; // 修正C函数的FFI签名:argv的类型是Pointer<Pointer<Utf8>>,对应C的char** argv typedef benchmark_hexagon_main_test = Int32 Function(Int32 argc, Pointer<Pointer<Utf8>> argv); // Dart对应的函数类型 typedef benchmarkHexagonMainTest = int Function(int argc, Pointer<Pointer<Utf8>> argv); static Future<RunTime> benchmarkMainTest(String f, int P, int l) async { final DynamicLibrary libBenchmark = Platform.isAndroid ? DynamicLibrary.open("libbenchmark.so") : DynamicLibrary.process(); final benchmarkHexagonMainTest hexagonBenchmark = libBenchmark .lookup<NativeFunction<benchmark_hexagon_main_test>>("benchmark_test_main_start") .asFunction(); // 1. 整理所有命令行参数为字符串列表 final List<String> args = [ "Program", "-f", f, "-P", "$P", "-l", "$l", ]; final int argc = args.length; // 2. 转换每个字符串为Utf8指针,存入临时列表 final List<Pointer<Utf8>> argPointers = args.map((str) => str.toNativeUtf8()).toList(); // 3. 分配指针数组,长度为argc + 1(最后加NULL标记结束) final Pointer<Pointer<Utf8>> argv = calloc<Pointer<Utf8>>(argc + 1); // 4. 填充指针数组 for (int i = 0; i < argc; i++) { argv[i] = argPointers[i]; } // 最后一个元素必须设为NULL argv[argc] = nullptr; try { // 调用C函数,传入正确的argc和argv hexagonBenchmark(argc, argv); } finally { // 5. 释放所有分配的内存,避免泄漏 calloc.free(argv); for (final ptr in argPointers) { calloc.free(ptr); } } // 这里补充你的RunTime返回逻辑,原代码未实现,请自行完善 return RunTime(...); }
关键修改说明
- 修正了FFI签名:把
argv的类型从Pointer<Utf8>改为Pointer<Pointer<Utf8>>,这才符合C语言中char *argv[](等价于char **argv)的类型定义。 - 模拟C的argv结构:不再尝试构造带空字符的单一字符串,而是用指针数组完全复刻C环境下的
argv格式。 - 增加内存管理:在
finally块中释放所有通过calloc分配的内存,这在FFI调用中是必须的,否则会造成内存泄漏。
内容的提问来源于stack exchange,提问作者Vikram Kapoor
相关产品推荐
相关产品推荐

