Dart FFI使用 常用对象方法介绍

2,601 阅读2分钟

这是我参与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语言的数据结构的映射关系,有兴趣的请关注。

Github仓库