使用 dart:ffi 綁定原生 macOS 程式碼
Flutter 行動裝置和桌面應用程式可以使用 dart:ffi 函式庫來呼叫原生 C API。FFI 代表 外部函式介面。類似功能的其他術語包括原生介面和語言綁定。
在您的函式庫或程式可以使用 FFI 函式庫來綁定原生程式碼之前,您必須確保原生程式碼已載入,並且其符號對 Dart 可見。本頁重點說明如何在 Flutter 外掛程式或應用程式中編譯、封裝和載入 macOS 原生程式碼。
本教學示範如何在 Flutter 外掛程式中綁定 C/C++ 原始碼,並在 macOS 上使用 Dart FFI 函式庫來綁定它們。在本逐步解說中,您將建立一個實作 32 位元加法的 C 函式,然後透過名為「native_add」的 Dart 外掛程式公開它。
動態與靜態連結
#原生函式庫可以動態或靜態連結到應用程式中。靜態連結的函式庫會嵌入到應用程式的可執行映像檔中,並在應用程式啟動時載入。
可以使用 DynamicLibrary.executable
或 DynamicLibrary.process
載入靜態連結函式庫中的符號。
相反地,動態連結的函式庫會以應用程式內獨立的檔案或資料夾形式散佈,並依需求載入。在 macOS 上,動態連結的函式庫會以 .framework
資料夾形式散佈。
可以使用 DynamicLibrary.open
將動態連結的函式庫載入到 Dart 中。
API 文件可從Dart API 參考文件取得。
建立 FFI 外掛程式
#如果您已經有外掛程式,請跳過此步驟。
若要建立名為「native_add」的外掛程式,請執行下列動作
flutter create --platforms=macos --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/macos/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」(連結的框架和函式庫)區段。
已編譯 (動態) 函式庫 (macOS)
#若要將封閉原始碼函式庫新增至 Flutter macOS 桌面應用程式,請使用下列指示
- 依照 Flutter 桌面的指示來建立 Flutter 桌面應用程式。
- 在 Xcode 中開啟
yourapp/macos/Runner.xcworkspace
。- 將您預先編譯的函式庫 (
libyourlibrary.dylib
) 拖曳到Runner/Frameworks
中。 - 按一下
Runner
並前往「Build Phases
」(建置階段)索引標籤。- 將
libyourlibrary.dylib
拖曳到「Copy Bundle Resources
」(複製套件資源)清單中。 - 在「
Embed Libraries
」(嵌入函式庫)下,勾選「Code Sign on Copy
」(複製時進行程式碼簽署)。 - 在「
Link Binary With Libraries
」(連結二進位檔與函式庫)下,將狀態設定為「Optional
」(可選)。(我們使用動態連結,無需靜態連結。)
- 將
- 按一下
Runner
並前往「General
」(一般)索引標籤。- 將
libyourlibrary.dylib
拖曳到「Frameworks, Libraries and Embedded Content」(框架、函式庫和嵌入內容)清單中。 - 選取「Embed & Sign」(嵌入和簽署)。
- 將
- 按一下「Runner」(執行器)並前往「Build Settings」(建置設定)索引標籤。
- 在「Search Paths」(搜尋路徑)區段中,設定「Library Search Paths」(函式庫搜尋路徑)以包含
libyourlibrary.dylib
所在的目錄路徑。
- 在「Search Paths」(搜尋路徑)區段中,設定「Library Search Paths」(函式庫搜尋路徑)以包含
- 將您預先編譯的函式庫 (
- 編輯
lib/main.dart
。- 使用
DynamicLibrary.open('libyourlibrary.dylib')
動態連結到符號。 - 在 widget 中的某處呼叫您的原生函式。
- 使用
- 執行
flutter run
並檢查您的原生函式是否被呼叫。 - 執行
flutter build macos
以建置應用程式的獨立發行版本。
其他資源
#若要深入了解 C 互通性,請查看下列影片
除非另有說明,否則本網站上的文件反映 Flutter 的最新穩定版本。頁面上次更新於 2024-11-19。 檢視原始碼 或回報問題。