通过查阅flutter官方文档,我们惊喜地发现flutter官方提供了一个dart:ffi(Foreign Function Interface: 外部功能接口)库来调用本地的 C API。下面我们就一起来看看如何将C代码集成到flutter项目中并且调用其中的方法。
安卓为例:创建一个 android/CMakeLists.txt 文件用来定义如何编译源文件,位置随意,可以在android目录下也可以在android/app或android/app/main/src/cpp都行,只要在后面的gradle添加正确路径即可,这里以android/app目录下为例。
cmake_minimum_required(VERSION 3.4.1) # for example # find_library( # Defines the name of the path variable that stores the # # location of the NDK library. # log-lib # # Specifies the name of the NDK library that # # CMake needs to locate. # log ) add_library(native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). app/src/main/cpp/native-lib.cpp) target_link_libraries( native-lib log )
添加一个 externalNativeBuild 到你的 android/build.gradle 文件中。示例如下
plugins { id "com.android.application" id "kotlin-android" id "dev.flutter.flutter-gradle-plugin" } def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) } } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { flutterVersionName = '1.0' } //flutter toast需要最低21版本 flutter.minSdkVersion = 21 android { namespace "com.lee.demo.flutter_demo" compileSdk flutter.compileSdkVersion ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } sourceSets { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.lee.demo.flutter_demo" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug } } externalNativeBuild { // Encapsulates your CMake build configurations. cmake { // Provides a relative path to your CMake build script. path "../CMakeLists.txt" } } } flutter { source '../..' } dependencies {}
这样最终会生成一个动态链接库.so文件
使用 FFI 库绑定本地代码
接下来,我们需要在 lib/my_native.dart文件中编写一些代码,将C代码函数转换成Dart代码方法。
import 'dart:ffi'; import 'dart:io'; class NativeLib { //函数声明 late final int Function(int x, int y) funcAdd; //初始化 NativeLib() { final DynamicLibrary nativeLib = Platform.isAndroid ? DynamicLibrary.open('libnative-lib.so') : DynamicLibrary.process(); //静态链接中的符号可以使用 DynamicLibrary.executable //或 DynamicLibrary.process 来加载。 //动态链接库在 Dart 中可以通过 DynamicLibrary.open 加载。 //函数定义 funcAdd = nativeLib .lookup<NativeFunction<Int32 Function(Int32, Int32)>>('native_add') .asFunction(); } }
不同平台加载库方式也不同,以下作为参考
const String _libName = 'hello'; /// The dynamic library in which the symbols for [HelloBindings] can be found. final DynamicLibrary _dylib = () { if (Platform.isMacOS || Platform.isIOS) { return DynamicLibrary.open('$_libName.framework/$_libName'); } if (Platform.isAndroid || Platform.isLinux) { return DynamicLibrary.open('lib$_libName.so'); } if (Platform.isWindows) { return DynamicLibrary.open('$_libName.dll'); } throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}'); }(); /// The bindings to the native functions in [_dylib]. final HelloBindings _bindings = HelloBindings(_dylib); int sum(int a, int b) => _bindings.sum(a, b);
也可以通过以下命令生成dart使用文件
flutter pub run ffigen --config ffigen.yaml
使用非常简单
void main() { debugPrint('native add:8+9=${NativeLib().funcAdd(8, 9)}'); runApp(const MyApp()); }
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2300
- 用户1336
- 访客10853847
每日一句
Challenges spark life; conquering them gives purpose.
挑战点亮生活,征服赋予意义。
挑战点亮生活,征服赋予意义。
新会员