Flutter 移動和桌面應用可以使用 dart:ffi 庫呼叫原生 C API。FFI外部函式介面 的縮寫。其他類似的術語包括原生介面語言繫結

在您的庫或程式可以使用 FFI 庫繫結到原生程式碼之前,您必須確保原生程式碼已載入並且其符號對 Dart 可見。本頁重點介紹在 Flutter 外掛或應用中編譯、打包和載入 macOS 原生程式碼。

本教程演示瞭如何在 Flutter 外掛中捆綁 C/C++ 原始檔,並使用 Dart FFI 庫在 macOS 上繫結到它們。在本演練中,您將建立一個 C 函式來實現 32 位加法,然後透過一個名為“native_add”的 Dart 外掛將其公開。

動態連結與靜態連結

#

原生庫可以動態或靜態地連結到應用中。靜態連結庫嵌入到應用的 executables 映像中,並在應用啟動時載入。

可以透過 DynamicLibrary.executableDynamicLibrary.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.executableDynamicLibrary.process 進行解析。

平臺庫

#

要連結到平臺庫,請使用以下說明

  1. 在 Xcode 中,開啟 Runner.xcworkspace
  2. 選擇目標平臺。
  3. 在 **Linked Frameworks and Libraries** 部分單擊 **+**。
  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. 將框架檔案新增到 **Embedded Binaries** 部分。
  3. 也將其新增到 Xcode 中目標的 **Linked Frameworks & Libraries** 部分。

已編譯(動態)庫(macOS)

#

要為 Flutter macOS 桌面 應用新增閉源庫,請按照以下說明操作:

  1. 按照 Flutter 桌面應用的說明建立 Flutter 桌面應用。
  2. 在 Xcode 中開啟 yourapp/macos/Runner.xcworkspace
    1. 將您的預編譯庫(libyourlibrary.dylib)拖到 Runner/Frameworks 資料夾中。
    2. 單擊 Runner 並轉到 **Build Phases** 選項卡。
      1. libyourlibrary.dylib 拖到 **Copy Bundle Resources** 列表中。
      2. Embed Libraries 下,勾選 Code Sign on Copy
      3. Link Binary With Libraries 下,將狀態設定為 Optional。(我們使用動態連結,無需靜態連結。)
    3. 單擊 Runner 並轉到 **General** 選項卡。
      1. libyourlibrary.dylib 拖到 **Frameworks, Libraries and Embedded Content** 列表中。
      2. 選擇 **Embed & Sign**。
    4. 單擊 **Runner** 並轉到 **Build Settings** 選項卡。
      1. 在 **Search Paths** 部分配置 **Library Search Paths**,以包含 libyourlibrary.dylib 所在路徑。
  3. 編輯 lib/main.dart
    1. 使用 DynamicLibrary.open('libyourlibrary.dylib') 來動態連結符號。
    2. 在小部件中的某個位置呼叫您的原生函式。
  4. 執行 flutter run 並檢查您的原生函式是否被呼叫。
  5. 執行 flutter build macos 來構建一個自包含的釋出版本應用。

其他資源

#

要了解更多關於 C 互操作性的資訊,請檢視以下影片