Dart FFI的简单分析

本文详细探讨了Dart的Foreign Function Interface(FFI),包括源码的位置,如何通过lookup获取函数指针,以及asFunction的实现细节,尤其是TrampolineFunction在其中的作用。

本文是阅读dart ffi相关的代码记录。

源码的位置

分成几个部分,dart的代码在sdk/lib/ffi下,有4个文件

  • annotations.dart
  • dynamic_library.dart : 定义DynamicLibrary类,用于加载so库
  • ffi.dart 定义Pointer类
  • native_type.dart 定义NativeType

Pointer相关的实际实现的代码,
在runtime/lib/ffi_path.dart, 定义的对应的native实现,关键的如

  • Pointer.asFunction对应 Ffi_asFunction
  • fromFunction 对应Ffi_fromFunction
  • 等等

runtime/lib/ffi_dynamic_library_patch.dart定义DynamicLibrary的实现

  • DynamicLibrary._open对应 Ffi_dl_open
  • DynamicLibrary.lookup 对应 Ffi_dl_lookup
  • 等等

对应的c++类
runtime/lib/ffi_dynamic_library.cc 实现open, loopkup等函数
runtime/lib/ffi.cc 实现fromFunction, asFunction等函数

lookup取得函数指针

dart的用法

import 'dart:ffi' as ffi;
import 'dart:io' show Platform;

// FFI signature of the hello_world C function
typedef hello_world_func = ffi.Void Function();
// Dart type definition for calling the C foreign function
typedef HelloWorld = void Function();

main() {
  // Open the dynamic library
  var path = "./hello_library/libhello.so";
  if (Platform.isMacOS) path = './hello_library/libhello.dylib';
  if (Platform.isWindows) path = r'hello_library\Debug\hello.dll';
  fi
### 使用 Dart FFI 调用 Go 函数 为了使 Dart 和 Go 进行互操作,通常的做法是利用 C 作为中间层。因为 Dart 的 Foreign Function Interface (FFI) 主要设计用于与 C 接口交互,而 Go 支持创建可导出为 C 库的函数。 #### 创建 Go 文件并编译成共享库 首先,在 Go 中定义希望暴露给外部调用者使用的功能,并确保这些功能遵循 `//export` 注释语法以便于构建时被识别出来: ```go package main import "C" import ( "fmt" ) //export AddNumbers func AddNumbers(a int, b int) int { return a + b } func main() {} ``` 接着,将上述代码保存在一个 `.go` 文件里(比如叫它 `add.go`),之后可以通过命令行工具将其编译成为动态链接库文件(Linux 上通常是 .so 文件;Windows 是 .dll 文件)。对于 Linux 用户来说,这一步骤如下所示: ```bash gcc -o libadd.so -shared -fPIC add.go ``` 请注意实际执行此指令前可能还需要安装额外依赖项以及设置环境变量等准备工作。 #### 编写 Dart 程序来加载和使用这个共享库中的函数 现在有了一个名为 `libadd.so` 的共享对象文件,接下来就是在 Dart 中编写相应的逻辑去访问其中的内容了。下面是一段简单的示例代码展示怎样完成这项工作[^1]: ```dart import 'dart:ffi'; import 'package:ffi/ffi.dart'; typedef NativeAddNumbers = Int32 Function(Int32 a, Int32 b); typedef AddNumbersDart = int Function(int a, int b); void main() async { final DynamicLibrary nativeLib = Platform.isAndroid || Platform.isIOS ? DynamicLibrary.open('libadd.so') : DynamicLibrary.process(); final AddNumbersDart addNumbers = nativeLib.lookup<NativeFunction<NativeAddNumbers>>('AddNumbers').asFunction(); print(addNumbers(5,7)); // 输出应为12 } ``` 这段代码展示了如何导入必要的包、声明类型别名以匹配目标语言签名、打开包含所需符号的动态库实例化它们对应的 Dart 可调用接口版本最后测试性的调用了来自原生侧的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值