使用 dart:ffi 繫結到原生 iOS 程式碼
Flutter 移動和桌面應用可以使用 dart:ffi 庫呼叫原生 C API。FFI 是 外部函式介面 的縮寫。其他類似的術語包括原生介面和語言繫結。
在您的庫或程式可以使用 FFI 庫繫結到原生程式碼之前,您必須確保原生程式碼已載入並且其符號對 Dart 可見。本文件重點介紹在 Flutter 外掛或應用中編譯、打包和載入 iOS 原生程式碼。
本教程演示瞭如何在 Flutter 外掛中捆綁 C/C++ 原始檔,並使用 Dart FFI 庫在 iOS 上繫結它們。在本演練中,您將建立一個 C 函式來執行 32 位加法,然後透過一個名為“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。 - 將 framework 檔案新增到 **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 互操作性的資訊,請檢視以下影片