Dart ffi認識與應用
使用dart:ffi與C語言進行溝通
前情提要
某次需求要在手機上開啟文件,而文件本身有經透過C/C++來做加密,這時候dart:ffi就派上用場了。
什麼是dart:ffi
首先要講一下FFI(Foreign Function Interface),作為編寫程式的人來說,它是一種通用術語,所表達的是開發者可以透過某種語言去呼叫或橋接另一種語言,而Dart也不例外,它可以在Dart Native平台上(Dart Web目前不支援)使用dart:ffi函式庫和ffi包來達到這個目的,讓我們來橋接Dart code與Native code吧。
建立ffi plugin
這邊建議用官方推薦的方式來使用,透過create plugin新增插件後在裡面加入你的代碼。
1
$ flutter create --platforms=android,ios --template=plugin_ffi native_add
建立一個C++檔案
1
2
3
4
5
6
#include <stdint.h>
extern "C" __attribute__((visibility("default"))) __attribute__((used))
// Todo: FFI綁定C symbols,表示他會照C語言的方式進行編譯跟鏈結,並允許他被外部程序訪問。
int32_t native_add(int32_t x, int32_t y) {
return x + y;
}
指定C語言代碼目錄。
- 在android底下新增CMakeList.txt,並輸入這段做指定目錄。
1 2 3 4 5 6 7 8 9
# 專案的名稱 add_library( native_add # Sets the library as a shared library. SHARED # 指定Code目錄 ../ios/Classes/native_test.cpp )
- 到build.gradle 在android底下加一行
package
在pubspec.yaml中dependencies配置底下新增ffi
1
ffi: ^1.2.1
開始寫ffi
到lib目錄底下新增ffi.bridge.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
typedef AddFunction = Int32 Function(Int32 x, Int32 y);
typedef AddFunctionDart = int Function(int x, int y);
// Todo: typedef 聲明往這邊加
class FFIBridge {
late AddFunctionDart _addFunc;
FFIBridge() {
final dl = Platform.isAndroid
? DynamicLibrary.open('libnative_add.so')
: DynamicLibrary.process();
// Todo: Android 因為JVM的關係,只支援動態鏈結,在執行時會生成.so(ELF)名稱為"lib"+"pluginName"+".so",IOS則支援靜態鏈結
_addFunc = dl.lookup<NativeFunction<AddFunction>>('native_add').asFunction();
}
int calc(int a, int b) => _addFunc(a, b);
// Todo: 這邊新增一個calc Func,提供外部呼叫時使用
}
使用方法
跟平常使用別人的package一樣,在pubspec.yaml新增這個plugin,改一下Path後pub get,就可以直接import了。
結語
簡單的ffi就大功告成了!,其他部分還有資料類型對應等的問題,可以在C interop using dart:ffi去查詢。
This post is licensed under CC BY 4.0 by the author.