是什么
Dart FFI
(官方地址)是可以在Dart Native平台上运行的Dart移动、命令行和服务器应用上通过Dart FFI
来调用C代码的一个技术。简单来说,就是Dart与C互相调用的一种机制。Dart FFI
是Dart2.12.0版本后(同时包含在 Flutter 2.0 和以后的版本里),才作为稳定版本发布。
说到底,Dart语言也是因为Flutter使用了它才火起来的,所以Dart FFI
技术在Flutter应用中更能发挥它更强大的作用
解决的问题
- 可以同步调用C API,不像Flutter Channel一开始就是异步
- 调用C语言更快,不像之前需要通过Native中转(或者改Flutter引擎代码)
- 还可以封装替换Flutter Channel达到更快和支持同步的目地
简单使用
为了只看FFI的特性,我先不在Flutter平台上使用,仅仅用命令行Dart应用的方式来讲解。 本人工程环境:
运行环境 MacOS 10.15.6 GCC 12.0.0 cmake 3.20.1 make 3.81 dart 2.14.2
1. 创建项目
由于项目结构简单,直接手动创建项目
1). 创建pubspec.yaml
文件
2). 创建bin/main.dart
文件
3). 创建C环境,创建library
、library/build
文件夹
4). 创建library/sample.c
、library/sample.h
、library/sample.def
、CMakeLists.txt
文件
目录结构如下
代码语言:javascript复制|_ bin
|_ main.dart
|_ library
|_ build
|_ CMakeLists.txt
|_ sample.c
|_ sample.h
|_ sample.def
|_ pubspec.yaml
复制代码
2. pubspec.yaml引入FFI
在pubspec.yaml
文件中的dependencies
中加入ffi
、path
库
pubspec.yaml
代码语言:javascript复制name: ffi_sample
version: 0.0.1
description: 使用ffi及ffigen的例子
publish_to: none
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
path: ^1.7.0
ffi: ^1.1.2
复制代码
3. 编译C代码
在sample.h
中写简单的一个函数
sample.h
代码语言:javascript复制void hello_world();
复制代码
在sample.c
中实现
sample.c
代码语言:javascript复制#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
void hello_world()
{
printf("Hello Worldn");
}
复制代码
sample.def
中简单导出
LIBRARY sample
EXPORTS
sample
复制代码
写编译使用的CMakeLists.txt
文件
cmake_minimum_required(VERSION 3.7 FATAL_ERROR)
project(sample_library VERSION 1.0.0 LANGUAGES C)
add_library(sample_library SHARED sample.c sample.def)
add_executable(sample_test sample.c)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set_target_properties(sample_library PROPERTIES
PUBLIC_HEADER sample.h
VERSION ${PROJECT_VERSION}
SOVERSION 1
OUTPUT_NAME "sample"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Hex_Identity_ID_Goes_Here"
)
复制代码
3. 编译C文件
现在所有文件都准备就绪,就可以编译C代码了。
1). 命令行进入到library/build
文件夹下
2). 执行cmake ..
生成编译所需文件
3). 执行make
编译
cd library/build
cmake ..
make
复制代码
如果在library/build
文件夹下生成了libsample.1.0.0.dylib
文件,那么说明编译成功了。
4. 写Dart通信代码
在bin/main.dart
中调用C
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'dart:io' show Platform, Directory;
import 'package:path/path.dart' as path;
void main() {
void main() {
// 初始化互调框架
var libraryPath =
path.join(Directory.current.path, 'ibrary', 'build', 'libsample.so');
if (Platform.isMacOS) {
libraryPath = path.join(
Directory.current.path, 'library', 'build', 'libsample.dylib');
}
if (Platform.isWindows) {
libraryPath =
path.join(Directory.current.path, 'library', 'Debug', 'libsample.dll');
}
final dylib = DynamicLibrary.open(libraryPath);
// *************** 1. Dart调用C方法 **************
final Pointer<T> Function<T extends NativeType>(String symbolName)
_lookup;
_lookup = dylib.lookup;
late final _hello_worldPtr =
_lookup<NativeFunction<Void Function()>>('hello_world');
late final _hello_world = _hello_worldPtr.asFunction<void Function()>();
// 调用C方法(无参)
_hello_world();
}
复制代码
5. 运行代码
现在,在命令行的项目根目录下运行
代码语言:javascript复制dart run bin/main.dart
复制代码
如果输出
代码语言:javascript复制Hello World
复制代码
说明调用成功
总结
上面就是Dart FFI
简单的示例了,后面我会继续更新,详细介绍Dart FFI
使用,欢迎关注。上面的代码我都打包放到Github了,Github地址