Flutter 如何使用 Dart FFI 和 Golang 進(jìn)行調(diào)用
本項(xiàng)目提供了一個(gè)完整的基礎(chǔ)框架,演示如何使用 Flutter 的 Dart FFI(Foreign Function Interface)直接調(diào)用 Golang 代碼,并支持所有 Flutter 平臺(tái)(Android、iOS、Windows、macOS、Linux 和 Web)。通過此框架,開發(fā)者可以省去傳統(tǒng)的通過平臺(tái)代碼(如 Java/Kotlin、Swift/Objective-C)橋接的繁瑣步驟,直接實(shí)現(xiàn) Dart 與 Golang 的交互。
功能簡介
- 跨平臺(tái)支持:支持 Android、iOS、Windows、macOS、Linux 和 Web 平臺(tái)。
- 純 FFI 調(diào)用:無需通過平臺(tái)中間代碼轉(zhuǎn)換,Dart 可直接調(diào)用 Golang 方法。
- 示例 Demo:實(shí)現(xiàn)了一個(gè)從 Golang 定時(shí)回調(diào)當(dāng)前時(shí)間到 Flutter 的功能。
- 簡單集成:開發(fā)者僅需 minimal 配置,即可在項(xiàng)目中直接使用。
- Web 兼容:支持 Web 平臺(tái),但要求 Golang 代碼中不存在 IO 操作。
框架工作原理
-
Dart FFI:通過 Dart FFI,F(xiàn)lutter 項(xiàng)目直接調(diào)用本地 Golang 動(dòng)態(tài)庫(如
.so、.dylib、.dll)。 - Web 平臺(tái)支持:通過 Golang 的 WebAssembly 輸出,使 Dart 能夠在 Web 平臺(tái)運(yùn)行 Golang 代碼。
- 統(tǒng)一接口:框架提供統(tǒng)一的接口規(guī)范,開發(fā)者只需遵循規(guī)范聲明和實(shí)現(xiàn)接口,無需處理底層平臺(tái)差異。
使用指南
1. 下載和初始化項(xiàng)目
克隆本項(xiàng)目到您的本地開發(fā)環(huán)境:
git clone https://github.com/yaooort/go2flutter.git
cd go2flutter
2. 編譯 Golang 代碼
Golang 代碼庫位于 core 目錄下,您需要將希望暴露給 Flutter 調(diào)用的方法分別定義在以下文件中:
-
原生平臺(tái):
core/export/cgo/main.go -
Web 平臺(tái):
core/export/web/main.go
框架已提供一個(gè)示例代碼(定時(shí)器回調(diào)當(dāng)前時(shí)間),可參考擴(kuò)展。完成方法定義后,運(yùn)行以下命令編譯所有平臺(tái)的 Golang 動(dòng)態(tài)庫:
make all
編譯完成后,生成的庫文件位于 core/build 目錄:
- 原生動(dòng)態(tài)庫(如
.so、.dll、.dylib)位于core/build/native。 - WebAssembly 文件(
.wasm)位于core/build/web。
3. 在 Flutter 中聲明 Golang 方法
- 打開 Flutter 項(xiàng)目的
lib/src/native_interface.dart文件。 - 按以下方式聲明并實(shí)現(xiàn) Golang 方法:
- 聲明與 Golang 對應(yīng)的函數(shù)接口。
- 為 Web 平臺(tái)實(shí)現(xiàn)特定的調(diào)用邏輯。
- 為其他平臺(tái)實(shí)現(xiàn)通用的 FFI 調(diào)用。
以下是一個(gè)示例接口聲明:
class Message {
late final String errMsg;
late final String message;
late final int code;
Message(this.errMsg, this.message, this.code);
}
typedef OnMessage = void Function(Message message);
// 定義一個(gè)抽象類作為標(biāo)準(zhǔn)橋梁
abstract class NativeLibraryInterface {
// test get go time
String getTime();
// 初始化
Future<bool> init(OnMessage onMessage, {String token});
// 停止
stopWork();
}
具體實(shí)現(xiàn)請參考框架中已提供的 native_native_interface.dart 和 web_native_interface.dart 文件。
4. 在項(xiàng)目中引入插件
在您的 Flutter 項(xiàng)目的 pubspec.yaml 文件中添加以下依賴:
dependencies:
go:
path: ./go2flutter
確保將路徑指向本框架的實(shí)際路徑。
5. 使用示例
框架提供了一個(gè) example 功能:Golang 定時(shí)器每秒回調(diào)當(dāng)前時(shí)間到 Flutter。以下是示例用法:
// 初始化平臺(tái)版本
NativeLibrary().init((message) {
setState(() {
_platformVersion = message.message;
});
}).then((bool isOk) {
setState(() {
_isOk = isOk;
});
if (kDebugMode) {
print("初始化go:$isOk");
}
});
SnackBar(
content: Text('獲取的時(shí)間: ${NativeLibrary().getTime()}'),
duration: const Duration(seconds: 2),
),
運(yùn)行 Flutter 應(yīng)用后,您將在控制臺(tái)中看到 Go 端定時(shí)返回的時(shí)間。
項(xiàng)目目錄結(jié)構(gòu)
go2flutter/
│
├── core/ # Golang 代碼庫
│ ├── export/ # Golang 方法定義目錄
│ │ ├── cgo/ # 原生平臺(tái)方法
│ │ └── web/ # Web 平臺(tái)方法
│ └── ... # 其他 Golang 源文件
│
├── lib/ # Flutter 代碼庫
│ ├── src/ # FFI 和接口實(shí)現(xiàn)
│ │ ├── native_interface.dart # 接口聲明
│ │ ├── native_universal.dart # 原生平臺(tái)實(shí)現(xiàn)
│ │ └── native_web.dart # Web 平臺(tái)實(shí)現(xiàn)
│ └── ...
注意事項(xiàng)
-
Web 平臺(tái)限制:
- Golang 代碼在 Web 平臺(tái)上運(yùn)行時(shí),不支持 IO 操作。
- 需要通過 WebAssembly 編譯生成
.wasm文件。
-
編譯工具鏈要求:
- 需要安裝
make工具。 - Golang 環(huán)境版本要求:1.17 及以上。
- 需要安裝
-
動(dòng)態(tài)庫兼容性:
- 各平臺(tái)編譯的動(dòng)態(tài)庫文件需與運(yùn)行環(huán)境匹配。
- 生成的動(dòng)態(tài)庫文件包含平臺(tái)差異,請確保正確加載。
開發(fā)者擴(kuò)展
-
新增 Golang 方法:
- 在
core/export/cgo/main.go或core/export/web/main.go中定義方法。 - 確保方法簽名符合框架規(guī)范。
- 在
-
擴(kuò)展 Dart 接口:
- 在
lib/src/native_interface.dart中添加方法聲明。 - 在
native_native_interface.dart和web_native_interface.dart中實(shí)現(xiàn)。
- 在
支持和貢獻(xiàn)
歡迎貢獻(xiàn)代碼或提交問題報(bào)告!如果您在使用中遇到問題,請通過 Issue 與我們聯(lián)系。
結(jié)語
通過本項(xiàng)目,開發(fā)者可以方便地在 Flutter 項(xiàng)目中調(diào)用 Golang 方法,無需處理平臺(tái)中間代碼轉(zhuǎn)換,簡化了開發(fā)流程。希望您能從中獲益! ??