跳至主要内容

使用 dart:ffi 绑定到原生 iOS 代码

Flutter 移动和桌面应用可以使用 dart:ffi 库来调用原生 C API。FFI 代表 外部函数接口。 其他表示类似功能的术语包括原生接口语言绑定。

在您的库或程序可以使用 FFI 库绑定到原生代码之前,您必须确保已加载原生代码并且其符号对 Dart 可见。此页面重点介绍在 Flutter 插件或应用中编译、打包和加载 iOS 原生代码。

本教程演示了如何在 Flutter 插件中捆绑 C/C++ 源代码,并在 iOS 上使用 Dart FFI 库绑定到它们。在本演练中,您将创建一个实现 32 位加法的 C 函数,然后通过名为“native_add”的 Dart 插件公开它。

动态链接与静态链接

#

原生库可以动态或静态地链接到应用中。静态链接库嵌入到应用的可执行映像中,并在应用启动时加载。

可以使用 DynamicLibrary.executableDynamicLibrary.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.executableDynamicLibrary.process 解析静态链接到应用二进制文件中的符号。

平台库

#

要链接到平台库,请使用以下说明

  1. 在 Xcode 中,打开 Runner.xcworkspace
  2. 选择目标平台。
  3. 在“已链接的框架和库”部分中单击+
  4. 选择要链接到的系统库。

第一方库

#

第一方原生库可以作为源代码或 (已签名的) .framework 文件包含。可能也可以包含静态链接的存档,但这需要测试。

源代码

#

要直接链接到源代码,请使用以下说明

  1. 在 Xcode 中,打开 Runner.xcworkspace

  2. 将 C/C++/Objective-C/Swift 源文件添加到 Xcode 项目中。

  3. 在导出的符号声明中添加以下前缀,以确保它们对 Dart 可见

    C/C++/Objective-C

    objc
    extern "C" /* <= C++ only */ __attribute__((visibility("default"))) __attribute__((used))

    Swift

    swift
    @_cdecl("myFunctionName")

已编译(动态)库

#

要链接到已编译的动态库,请使用以下说明

  1. 如果存在正确签名的 Framework 文件,请打开 Runner.xcworkspace
  2. 将框架文件添加到“嵌入式二进制文件”部分。
  3. 还将其添加到 Xcode 中目标的“已链接的框架和库”部分。

开源第三方库

#

要创建一个包含 C/C++/Objective-C 和 Dart 代码的 Flutter 插件,请使用以下说明

  1. 在您的插件项目中,打开 ios/<myproject>.podspec
  2. 将原生代码添加到 source_files 字段中。

然后,原生代码将静态链接到使用此插件的任何应用的应用二进制文件中。

闭源第三方库

#

要创建一个包含 Dart 源代码但以二进制形式分发 C/C++ 库的 Flutter 插件,请使用以下说明

  1. 在您的插件项目中,打开 ios/<myproject>.podspec
  2. 添加 vendored_frameworks 字段。请参阅 CocoaPods 示例

剥离 iOS 符号

#

创建发布归档文件 (IPA) 时,Xcode 会剥离符号。

  1. 在 Xcode 中,转到目标 Runner > 构建设置 > 剥离样式
  2. 所有符号更改为非全局符号

其他资源

#

要了解有关 C 互操作性的更多信息,请查看以下视频