使用 dart:ffi 绑定到原生 iOS 代码
要在 Flutter 程序中使用 C 代码,请使用 dart:ffi 库。
Flutter 移动和桌面应用可以使用 dart:ffi 库调用原生 C API。FFI 是 外部函数接口 的缩写。其他类似的术语包括原生接口和语言绑定。
在您的库或程序可以使用 FFI 库绑定到原生代码之前,您必须确保原生代码已加载并且其符号对 Dart 可见。此页面重点介绍在 Flutter 插件或应用程序中编译、打包和加载 iOS 原生代码。
本教程演示了如何在 Flutter 插件中捆绑 C/C++ 源代码,并使用 Dart FFI 库在 iOS 上绑定到它们。在本演练中,您将创建一个实现 32 位加法的 C 函数,然后通过名为“native_add”的 Dart 插件将其暴露出来。
动态链接与静态链接
#原生库可以动态或静态地链接到应用中。静态链接库嵌入到应用的 executables 映像中,并在应用启动时加载。
可以使用 DynamicLibrary.executable 或 DynamicLibrary.process 加载静态链接库中的符号。
与此相反,动态链接库以单独的文件或文件夹的形式分发在应用程序中,并按需加载。在 iOS 上,动态链接库以 .framework 文件夹的形式分发。
可以使用 DynamicLibrary.open 将动态链接库加载到 Dart 中。
API 文档可从 Dart API 参考文档 获取。
创建 FFI 插件
#要创建一个名为“native_add”的 FFI 插件,请执行以下操作
flutter create --platforms=android,ios,macos,windows,linux --template=plugin_ffi native_add
cd native_add
这将在 native_add/src 中创建一个包含 C/C++ 源代码的插件。这些源代码由不同操作系统构建文件夹中的原生构建文件构建。
FFI 库只能绑定 C 符号,因此在 C++ 中,这些符号会被标记为 extern "C"。
您还应该添加属性来指示这些符号是从 Dart 引用的,以防止链接器在链接时优化期间丢弃这些符号。__attribute__((visibility("default"))) __attribute__((used))。
在 iOS 上,native_add/ios/native_add.podspec 链接代码。
原生代码在 lib/native_add_bindings_generated.dart 中从 Dart 调用。
绑定是使用 package:ffigen 生成的。
其他用例
#iOS 和 macOS
#动态链接库在应用程序启动时由动态链接器自动加载。可以使用 DynamicLibrary.process 解析其组成符号。您还可以使用 DynamicLibrary.open 获取库的句柄,以限制符号解析的范围,但尚不清楚 Apple 的审核流程如何处理此问题。
可以静态链接到应用程序二进制文件中的符号可以使用 DynamicLibrary.executable 或 DynamicLibrary.process 解析。
平台库
#要链接到平台库,请使用以下说明
- 在 Xcode 中,打开
Runner.xcworkspace。 - 选择目标平台。
- 在 Linked Frameworks and Libraries 部分中单击 +。
- 选择要链接的系统库。
第一方库
#第一方原生库可以作为源代码或(已签名).framework 文件包含。可能也可以包含静态链接的存档,但这需要测试。
源代码
#要直接链接到源代码,请使用以下说明
在 Xcode 中,打开
Runner.xcworkspace。-
将 C/C++/Objective-C/Swift 源代码文件添加到 Xcode 项目。
-
为了确保它们对 Dart 可见,请将以下前缀添加到导出的符号声明
C/C++/Objective-C
objcextern "C" /* <= C++ only */ __attribute__((visibility("default"))) __attribute__((used))Swift
swift@_cdecl("myFunctionName")
编译后的(动态)库
#要链接到编译后的动态库,请使用以下说明
- 如果存在正确签名的
Framework文件,请打开Runner.xcworkspace。 - 将框架文件添加到目标的 Embedded Binaries 部分。
- 同时将其添加到 Xcode 目标的 Linked Frameworks & Libraries 部分。
开源第三方库
#要创建一个包含 C/C++/Objective-C 和 Dart 代码的 Flutter 插件,请使用以下说明
- 在您的插件项目中,打开
ios/<myproject>.podspec。 - 将原生代码添加到
source_files字段。
然后,原生代码将静态链接到使用此插件的任何应用程序的应用程序二进制文件中。
闭源第三方库
#要创建一个包含 Dart 源代码的 Flutter 插件,但以二进制形式分发 C/C++ 库,请使用以下说明
- 在您的插件项目中,打开
ios/<myproject>.podspec。 - 添加一个
vendored_frameworks字段。请参阅 CocoaPods 示例。
移除 iOS 符号
#在创建发布存档 (IPA) 时,Xcode 会移除符号。
- 在 Xcode 中,转到 Target Runner > Build Settings > Strip Style。
- 从 All Symbols 更改为 Non-Global Symbols。
其他资源
#要了解更多关于 C 互操作性的信息,请查看以下视频