这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
为了联通Dart与C语言,Dart FFI
提供了很多方法,下面我来介绍一下主要的方法。
加载库
DynamicLibrary.open
它可以加载动态链接库
external factory DynamicLibrary.open(String path);
此方法用于加载库文件,如上一篇我编译C后生成的libsample.1.0.0.dylib
文件,我们需要使用此方法来将其加载到DartVM中。需要注意的是,多次调用此方法加载库文件也只会将库文件加载到DartVM中一次。
示例:
import 'dart:ffi' as ffi;
import 'package:path/path.dart' as path;
var libraryPath = path.join(
Directory.current.path, 'library', 'build', 'libsample.dylib');
final dylib = ffi.DynamicLibrary.open(libraryPath);
DynamicLibrary.process
external factory DynamicLibrary.process();
它可以用于在iOS及MacOS中加载应用程序已经自动加载好的动态链接库,也可以解析静态链接到应用的二进制文件符号。需要注意的是,它不能用于windows平台
DynamicLibrary.executable
external factory DynamicLibrary.executable();
它可用于加载静态链接库
NativeType
NativeType
是在Dart中表示C语言中的数据结构,有关数据结构的内容我会在下一篇分享。它不可在Dart中实例化,只能由Native返回。
Pointer
它是C语言中指针在Dart中的映射
DynamicLibrary->lookup()
external Pointer<T> lookup<T extends NativeType>(String symbolName);
它用于在DynamicLibrary中查找到对应的符号并返回其内存地址。
Dart
使用方法:
final dylib = DynamicLibrary.open(libraryPath);
late final _hello_worldPtr =
dylib.lookup<NativeFunction<Void Function()>>('hello_world');
late final _hello_world = _hello_worldPtr.asFunction<void Function()>();
_hello_world();
Pointer.fromAddress(int ptr)
根据内存地址获取C对象指针
例如:
// 创建一个指向NULL的Native指针
final Pointer<Never> nullptr = Pointer.fromAddress(0);
Pointer.fromFunction
根据一个Dart函数,创建一个Native函数指针,一般用于将Dart函数传给C,使C有调用Dart函数的能力
void globalCallback(int src, int result) {
print("globalCallback src=$src, result=$result");
}
Pointer.fromFunction(globalCallback);
Pointer->address()
获取指针的内存地址
asFunction
将Native指针对象,转换为Dart函数
sizeOf
返回具体类型的内存占用
例
ffi.sizeOf<ffi.Int64>(); // 8
malloc.allocate()
Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment});
开辟一块大小byteCount
的空间
例
Pointer<Uint8> bytes = malloc.allocate<Uint8>(ffi.sizeOf<ffi.Uint8>());
malloc.free
释放内存
malloc.free(bytes);
总结
Dart FFI
常见的方法就是这些了,基本掌握了这些方法就可以使用Dart随意操作C语言了。后续我将继续讲解Dart与C语言的数据结构的映射关系,有兴趣的请关注。