flutter项目使用FFI类型的插件

Home / Android MrLee 1月前 375

通过查阅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());
}


本文链接:https://www.it72.com/12761.htm

上传的附件:
推荐阅读
最新回复 (0)
返回