Skip to content

源码:labs/dart/host/bin/runtime_concurrency/ffi_demo.dart ​

  • 原始路径:labs/dart/host/bin/runtime_concurrency/ffi_demo.dart
  • 类型:dart
dart
// dart:ffi 零拷贝与原生函数调用演示(纯 dart:ffi,零外部依赖)
//
// 对应 docs 05-bridge-hybrid/06-native-thread-isolate-bridge.md:
// 1. DynamicLibrary.process() 拿进程符号表,lookup 原生函数
// 2. NativeFunction / Pointer / 类型映射(Int32/IntPtr/Void/Uint8)
// 3. malloc + asTypedList:Dart 直接读写 Native 内存(零拷贝)
// 4. 对照:FFI 无序列化开销 vs PlatformChannel 需切主线程 + 拷贝
//
// 运行:dart run bin/runtime_concurrency/ffi_demo.dart

import 'dart:ffi';

// C 函数签名声明(等价于 C 头文件里的函数原型)
typedef CGetpidNative = Int32 Function();
typedef CGetpidDart = int Function();

typedef CMallocNative = Pointer<Void> Function(IntPtr);
typedef CMallocDart = Pointer<Void> Function(int);

typedef CFreeNative = Void Function(Pointer<Void>);
typedef CFreeDart = void Function(Pointer<Void>);

void main() {
  // 1. 拿当前进程符号表(libc 的 malloc/free/getpid 都在)
  final libc = DynamicLibrary.process();

  print('=== 1. 调用 C 标准库函数 ===');
  final getpid = libc.lookupFunction<CGetpidNative, CGetpidDart>('getpid');
  print('  getpid() = ${getpid()}(Dart 直接调用 C 函数)');

  final malloc = libc.lookupFunction<CMallocNative, CMallocDart>('malloc');
  final free = libc.lookupFunction<CFreeNative, CFreeDart>('free');

  print('');
  print('=== 2. malloc + asTypedList:零拷贝读写 Native 内存 ===');
  final count = 8;
  final ptr = malloc(sizeOf<IntPtr>() * count).cast<Uint8>();
  // asTypedList:把 Native 内存包装成 Dart TypedData 视图(零拷贝,无复制)
  final view = ptr.asTypedList(count);
  for (var i = 0; i < count; i++) {
    view[i] = (i * 10); // 直接写 Native 内存
  }
  print('  通过 Dart 视图写入并读回: $view');
  print('  指针地址: 0x${ptr.address.toRadixString(16)}(C 堆上的真实地址)');

  // C 侧与 Dart 侧看到的是同一块内存(零拷贝语义)
  view[0] = 255;
  print('  修改后再次读回(同一块内存,无拷贝): ${ptr.asTypedList(count)[0]}');

  free(ptr.cast()); // 释放 Native 内存(必须,否则泄漏)

  print('');
  print('=== 3. 结论 ===');
  print('  dart:ffi 直接操作 Native 指针(Pointer<T>),无序列化/拷贝开销;');
  print('  对应 PlatformChannel 每次调用都要内存序列化 + 切主线程。');
  print('  注意:C++ 后台线程回调 Dart 仍须 Dart_PostCObject(见 docs 06)。');
}

站点构建时间:2026/8/24 23:43:17