前言:
最近在入坑 flutter ffi(筆者目前對(duì)flutter dart也不是很了解),先從最難的啃,網(wǎng)上現(xiàn)在關(guān)于 ffi的文章很少,對(duì)于新手而言不太友好,更別說(shuō)公開的視頻教程,更是少之又少,我也是摸索了很久才入一點(diǎn)門道(太菜了,哥哥們諒解),這里不做任何技術(shù)上的指導(dǎo),只是簡(jiǎn)簡(jiǎn)單單的入門。
分幾個(gè)步驟來(lái):
第一步:搭建flutter環(huán)境
第二步:創(chuàng)建flutter 新項(xiàng)目
第三步:引入 ffigen
第四步:引入 .h/.c 文件
第五步:使用 ffigen 生成dart上可執(zhí)行的簽名文件(dart語(yǔ)言不能直接調(diào)用c語(yǔ)言中的函數(shù),類似 Android中的 jni,需要做下中轉(zhuǎn))
第六步:編譯 C 代碼為動(dòng)態(tài)庫(kù)
第七步:加載動(dòng)態(tài)庫(kù)并調(diào)用內(nèi)部 C 函數(shù)
第八步:運(yùn)行
總結(jié)
廢話不多說(shuō),直接開干
一:搭建flutter ffigen所需環(huán)境
詳細(xì)看這里:https://codelabs.developers.google.com/codelabs/flutter-ffigen?hl=zh-cn#0
(主要看:安裝 LLVM,其它的看這篇文檔)
二:創(chuàng)建flutter 新項(xiàng)目
通過(guò)命令行創(chuàng)建 或 Android Studio,Visual Studio Code 編譯器創(chuàng)建都行
flutter create first_flutter_ffi_study_project
cd first_flutter_ffi_study_project
如果是通過(guò)模板生成的頂層 pubpsec.yaml 可能包含過(guò)時(shí)的 ffigen 軟件包版本。運(yùn)行以下命令,更新插件項(xiàng)目中的 Dart 依賴項(xiàng):
$ flutter pub upgrade --major-versions
三:引入 ffigen
flutter pub add ffi
flutter pub add ffigen --dev
// pubspec.yaml
......
dependencies:
ffi: ^2.1.3
.....
dev_dependencies:
ffigen: ^15.0.0
......
四:引入 .h/.c 文件
在項(xiàng)目根目錄創(chuàng)建 native 文件夾并新建 hello.h 和 hello.c 文件
mkdir native
cd native
touch hello.h
touch hello.c
// hello.h
#ifndef HELLO_H
#define HELLO_H
int sum(int a, int b);
#endif // HELLO_H
// hello.c
#include "hello.h"
int sum(int a, int b) {
return a + b;
}
五:使用 ffigen 生成 dart 和 C 綁定的簽名文件
首先,你需要編寫一個(gè) ffigen 配置文件。在項(xiàng)目的根目錄下創(chuàng)建一個(gè) ffigen.yaml 文件,內(nèi)容如下:
name: FFIBinding
description: FFI bindings for the native library.
output: lib/src/ffi_bindings.dart
headers:
entry-points:
- 'native/hello.h'
include-directives:
- 'native/hello.h'
然后,在終端中運(yùn)行 ffigen 命令生成 Dart 綁定:
flutter pub run ffigen --config ffigen.yaml
這會(huì)在 lib/src 目錄下生成一個(gè) ffi_bindings.dart 文件。
六:編譯 C 代碼為動(dòng)態(tài)庫(kù)
為了能夠在 Dart 中調(diào)用 c語(yǔ)言中的函數(shù),你需要先編譯 C 代碼為動(dòng)態(tài)庫(kù)。
在 macOS 上,導(dǎo)航到 native 文件夾,運(yùn)行以下命令:(這將在 native 目錄下生成 libhello.dylib 文件)
gcc -dynamiclib -o libhello.dylib hello.c
在 Windows 上,你可以使用 MinGW 或者 Visual Studio 的命令行工具來(lái)編譯。
使用 MinGW
安裝 MinGW,確保 gcc 在你的系統(tǒng)路徑中。
打開終端,導(dǎo)航到 native 文件夾,運(yùn)行以下命令:(這將在當(dāng)前目錄下生成 hello.dll 文件)
gcc -shared -o hello.dll hello.c
?。?!Android 和 ios 這里后面再補(bǔ)充(待更新)
七:加載動(dòng)態(tài)庫(kù)并調(diào)用內(nèi)部 C 函數(shù)
在 lib/main.dart 文件中導(dǎo)入生成的綁定文件,并調(diào)用 sum 函數(shù):
import 'package:flutter/material.dart';
import 'dart:ffi'; // 導(dǎo)入 FFI 包
import 'src/ffi_bindings.dart' as bindings; // 導(dǎo)入生成的綁定文件
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('FFI Example')),
body: Center(
child: ElevatedButton(
onPressed: () {
// 加載動(dòng)態(tài)庫(kù)
final DynamicLibrary nativeLib = DynamicLibrary.open('hello.dll'); // windows 使用 'hello.dll' 對(duì)于 macos,使用 'libhello.dylib'
// 獲取生成的綁定文件中的函數(shù)
final sumFunction = bindings.FFIBinding(nativeLib).sum;
// 調(diào)用函數(shù)
final result = sumFunction(10, 20);
print('Sum of 10 and 20 is $result');
},
child: Text('Call sum function'),
),
),
),
);
}
}
八:運(yùn)行
flutter run
點(diǎn)擊按鈕后,你應(yīng)該能在控制臺(tái)看到輸出:(至此已完成初步入門,然后再回顧下這幾個(gè)要點(diǎn))
Sum of 10 and 20 is 30
示例源碼:點(diǎn)這里
總結(jié):
通過(guò)上面的步驟,大致知道了,ffi 到底怎么開發(fā),以及 ffigen 到底怎么使用,從量變到質(zhì)變,加油少年!