01、Flutter FFI 最简示例

 
Flutter FFI 学习笔记系列

  1. 《Flutter FFI 最简示例》
  2. 《Flutter FFI 基础数据类型》
  3. 《Flutter FFI 函数》
  4. 《Flutter FFI 字符串》
  5. 《Flutter FFI 结构体》
  6. 《Flutter FFI 类》
  7. 《Flutter FFI 数组》
  8. 《Flutter FFI 内存管理》
  9. 《Flutter FFI Dart Native API》
      
     

  2021年3月份,官方宣布发布 Flutter 2.0 正式版,至此,FFI 终于不再是 beta 版本,而是正式稳定版。
  FFI (Foreign Function Interface)表示 外部功能接口,类似 JAVA 的 JNI。项目升级到 Flutter 2.0 之后,我们就可以使用 dart:ffi 库来调用 C 语言编写的代码。
 
  在某些开发场景下,使用 FFI 比使用 Channel 要好很多,FFI 不需要 await / async ,代码更自然、更舒适。
 
  官方 FFI 使用示例:https://flutter.cn/docs/development/platform-integration/c-interop
 
  需要注意一点:dart:ffi 库只能用来调用 C 语言 API,不支持调用 C++ 语言 API,因此,C++的代码需要包装成 C 风格才行。
 
  下面通过一个示例来演示 FFI 的基本使用步骤。
 

1、创建 Flutter 工程

  创建一个名称为 “native_add” 的工程,含 android 和 ios 平台:

flutter create --platforms=android,ios native_add
cd native_add

2、定义 C API

  新建 native_add.cpp 文件,位于 ios/Runner

cat ios/Runner/native_add.cpp 
#include <stdint.h>

extern "C" __attribute__((visibility("default"))) __attribute__((used))
int32_t native_add(int32_t x, int32_t y) {
    
    
    return x + y;
}

  可以将 C 代码放到 ios/Runner 目录下,因为 CocoaPods 不允许代码处于比 podspec 文件更高的目录层级,但是 Gradle 允许您指向 ios 文件夹。iOS 和 Android 可以共用一套C代码;当然,也可以将特定于 Android 的代码添加到 android 文件夹并修改 CMakeLists.txt 文件。
 
 dart:ffi 只允许和 C 符号进行绑定,因此如果是 C++ 编写的符号,需要添加 extern C 标记。另外,还应该添加属性来表明符号是被 Dart 引用的,这样可以防止链接器在优化链接时会丢弃符号,这里说的属性就是上面的 __attribute__((visibility("default"))) __attribute__((used))
 

3、不同平台的工程配置

3.1 iOS 平台配置

  在 iOS 中,您需要告诉 Xcode 如何静态链接这个文件,步骤如下:

  1. 使用 Xcode 打开 ios/Runner.xcworkspace
  2. 右键点击【Runner】目录,然后点击【Add Files to “Runner” …】;
  3. 添加 native_add.cpp 源码文件到 Xcode 工程中,如下图所示;

    在这里插入图片描述
     

3.2 Android 平台配置

  在 Android 中,需要在创建一个 CMakeLists.txt 文件用来定义如何编译源文件,同时告诉 Gradle 如何去定位它们。
 首先,在 android/app 目录中,创建 CMakeLists.txt 文件,内容如下:

cmake_minimum_required(VERSION 3.4.1)  # for example

add_library( native_add

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             ../../ios/Runner/native_add.cpp )

  然后,打开 android/app/build.gradle 文件,添加以下内容:

android {
    
    
	// ...
    externalNativeBuild {
    
    
        // Encapsulates your CMake build configurations.
        cmake {
    
    
          // Provides a relative path to your CMake build script.
          path "CMakeLists.txt"
        }
    }
    // ...
}

  最后,修改 android/app/local.properties 文件,添加一行代码 ndk.dir,如下:

sdk.dir=/Users/clarkwain/Developer/android_sdk
ndk.dir=/Users/clarkwain/Developer/android-ndk-r21e
flutter.sdk=/Users/clarkwain/Developer/flutter

  说明:

  • ndk.dir 表示指定NDK所在目录
     

4、Dart 中调用 C API

  上面完成各个平台的配置之后,接着就可以在 Dart 中编写调用 C 的函数了。

  首先,打开 lib/main.dart文件,修改为:

import 'package:flutter/material.dart';
import 'dart:ffi'; // For FFI
import 'dart:io'; // For Platform.isX

void main() {
    
    
  runApp(FFIDemo());
}

class FFIDemo extends StatefulWidget {
    
    
  const FFIDemo({
    
    Key key}) : super(key: key);

  @override
  _FFIDemoState createState() => _FFIDemoState();
}

class _FFIDemoState extends State<FFIDemo> {
    
    
  DynamicLibrary nativeAddLib;
  int Function(int x, int y) nativeAddFunc;

  @override
  void initState() {
    
    
    super.initState();

    //加载 C 符号
    nativeAddLib = Platform.isAndroid
        ? DynamicLibrary.open("libnative_add.so")
        : DynamicLibrary.process();

    //查找"native_add"符号,并转为 Dart 函数
    nativeAddFunc = nativeAddLib
        .lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add")
        .asFunction();
  }

  @override
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      home: Center(
        child: Text(
          "1+1=${nativeAddFunc(1, 1)}", //调用 C 的 native_add() 函数
        ),
      ),
    );
  }
}

5、运行效果如下:

  代码编写完之后,即可以运行看效果:
  
    
 

6.总结

  
  上面就是 Flutter FFI 的使用示例了,在后面的章节中,将会详细介绍 FFI 的使用,欢迎关注。
  
  
  
 

猜你喜欢

转载自blog.csdn.net/eieihihi/article/details/119117277