Flutter 上使用 C/C++ 代码(上)

简介: Flutter 上使用 C/C++ 代码(上)
+关注继续查看

在 Flutter 的 1.10.x 后的分支,dart:ffi 被并入 flutter,现在 flutter 中也可以使用 ffi 了。 这东西是啥玩意呢,就是让 dart 可以直接调用 c/c++ 代码等东西的库,FFI(foreign function interface), 官方文档在这里。 但是在当前版本中,这东西在官方说明中依然处于技术预览版,就是可用,但后续不保证 API 不变更。


开发环境


首先我是 mac 系统,windows 系统不保证脚本的可用和工具的可用,linux 的话可能一些必要工具需要使用自己平台的包管理工具,并且涉及到 iOS 部分, 必须使用 mac。

所有需要的工具包:

  • Xcode(或 XcodeBuild 命令行工具)
  • brew
  • clang
  • CMake
  • Android 工具链
    • Android SDK
    • NDK
    • Android Studio(可选)
    • Gradle
  • Flutter 工具链
    • SDK 1.10.x+
  • VSCode(可选,这东西看你的情况,作为示例的话只要是文本编辑器即可,我本人使用这个作为主要的文本编辑器)

这里说的是包含后续所有用到的东西,并不仅仅是本文。 其中对于 Flutter 开发者可能需要单独安装的应该只有 NDK 和 CMake,这两个东西是包含在 Android SDK 下的,可以使用 Android Studio 下载,也可以单独下载。


ffi 的简单介绍


根据官方文档说明

可以理解为,将 c 的类型和 dart 的类型关联起来,然后 ffi 会在内部将两端关联起来,完成调用。

有如下几种类型


image.png

image.png

image.png


基本就是对应 c 中的类型,对应 Void 各种长度的有无符号的整型、单双精度浮点、指针、方法。


转化的过程

C 源码核心就这点,打印即可。


void hello_world() {
    printf("Hello World\n");
}

导包,这个是第一步要做的。


import 'dart:ffi' as ffi;
// 定义一个 ffi 类型,包装成 c 识别的 typedef
typedef hello_world_func = ffi.Void Function();
// 将 ffi 类型定义为 dart 类型,返回值也统一成 typedef
typedef HelloWorld = void Function();
// 打开动态库, dylib 是 mac 上的动态库的后缀
final dylib = ffi.DynamicLibrary.open('hello_world.dylib');
// 这里是最难理解的一步, 后面会详细解说
final HelloWorld hello = dylib
    .lookup<ffi.NativeFunction<hello_world_func>>('hello_world')
    .asFunction();
// 调用
hello();


详细理解转化过程

这里以 lookup 方法为切入点,详细理解下这里做了什么,以便于后面我们可以自行完成这个过程,lookup 方法签名如下:

external Pointer<T> lookup<T extends NativeType>(String symbolName);


参数

很好理解,传入一个方法名,让我们能找到 c 方法。


泛型

这个是方法的类型签名的 dart:ffi 表现形式。c 方法的签名是这样的: void hello_world(),所以我们就需要一个对应的类型,也就是上面定义的 ffi 类型 ffi.Void Function()


返回类型

这里的返回值是用于在实际调用时,转化 c 方法的返回值为 dart 的类型来使用的,所以就是对应的 dart 类型。

/// 定义是这样的
void Function()
/// 接收的 asFunction 方法
final void Function() hello = XXXX;

写起来的时候可能是这样的。


实例

extern "C" {
// __attribute__((visibility("default"))) __attribute__((used)) // 虽然说需要这行, 但是没这行也没报错
int32_t native_add(int32_t x, int32_t y) { return x + y; }
double double_add(double x, double y) { return x + y; }
}
import 'dart:ffi';
final DynamicLibrary dylib = Platform.isAndroid
    ? DynamicLibrary.open("libnative_add.so")
    : DynamicLibrary.open("native_add.framework/native_add");
final int Function(int x, int y) nativeAdd = dylib
    .lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add")
    .asFunction();
final double Function(double, double) doubleAdd = dylib
    .lookup<NativeFunction<Double Function(Double, Double)>>("double_add")
    .asFunction();


打包和运行

在 dart vm 中,可以有多种方案,只要能编译出 dylib 即可,官方的 hello world 示例中是直接使用 CMake,内部使用 GCC 打包编译。

设置 dylib 的目录到环境变量中, 以便于运行时可以找到动态库。

#!/bin/bash
export DYLD_LIBRARY_PATH=.:$DYLD_LIBRARY_PATH


目录
相关文章
|
9天前
|
C++
LeetCode 43. 字符串相乘C++代码 超过100%
LeetCode 43. 字符串相乘C++代码 超过100%
27 0
|
26天前
|
PyTorch 算法框架/工具 C语言
Python调用C++代码
今天在研究PyTorch中Tensor的一些操作的时候,发现其底层Tensor的操作都是用C++写的,并使用[pybind11](https://github.com/pybind/pybind11)进行C++和Python的桥接。所以,我就想着探索一下Python中如何调用C++代码?
27 0
|
2月前
|
Linux C++
通过C/C++代码设置Linux系统时间的方法与实例
Linux系统中的时间设置是关键任务之一,涉及日志记录、数据同步等众多应用场景。本文将详细介绍如何通过C/C++代码设置Linux系统时间,包括调用系统调用和使用第三方库,同时提供实例演示。
256 2
|
2月前
|
C语言 C++
【哈夫曼树】基本概念、构建过程及C++代码
【哈夫曼树】基本概念、构建过程及C++代码
35 0
|
2月前
|
C++
【线索二叉树】C++代码及线索化过程详解
【线索二叉树】C++代码及线索化过程详解
29 0
|
2月前
|
编译器 Linux 测试技术
【C/C++】C语言工程转C++工程,去除旧代码中的警告和错误
将 C语言项目转为C++项目更新维护,处理旧代码中的警告和错误
45 0
|
2月前
|
算法 编译器 C++
【C++】SonarQube C++ 静态代码检视规则
SonarQube 静态代码检视相关的规则整理
321 0
|
3月前
|
存储 C++ 容器
使用C++编写一个图的深度和广度优先遍历的代码
使用C++编写一个图的深度和广度优先遍历的代码
26 0
|
3月前
|
C++
使用C++编写一个AVL的增删改查代码并附上代码解释
使用C++编写一个AVL的增删改查代码并附上代码解释
26 0
|
3月前
|
C++
C++之MFC制作简单计算器(VS2019实现),附带完整代码
C++之MFC制作简单计算器(VS2019实现),附带完整代码
36 0
热门文章
最新文章
相关产品
云迁移中心
推荐文章
更多