前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dart FFI使用 示例

Dart FFI使用 示例

作者头像
玖柒的小窝
修改2021-12-31 17:24:27
2K1
修改2021-12-31 17:24:27
举报
文章被收录于专栏:各类技术文章~各类技术文章~

是什么

Dart FFI(官方地址)是可以在Dart Native平台上运行的Dart移动、命令行和服务器应用上通过Dart FFI来调用C代码的一个技术。简单来说,就是Dart与C互相调用的一种机制。Dart FFI是Dart2.12.0版本后(同时包含在 Flutter 2.0 和以后的版本里),才作为稳定版本发布。

说到底,Dart语言也是因为Flutter使用了它才火起来的,所以Dart FFI技术在Flutter应用中更能发挥它更强大的作用

解决的问题

  1. 可以同步调用C API,不像Flutter Channel一开始就是异步
  2. 调用C语言更快,不像之前需要通过Native中转(或者改Flutter引擎代码)
  3. 还可以封装替换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环境,创建librarylibrary/build文件夹

4). 创建library/sample.clibrary/sample.hlibrary/sample.defCMakeLists.txt文件

目录结构如下

代码语言:javascript
复制
|_ bin
    |_ main.dart
|_ library
    |_ build
    |_ CMakeLists.txt
    |_ sample.c
    |_ sample.h
    |_ sample.def
|_ pubspec.yaml
复制代码

2. pubspec.yaml引入FFI

pubspec.yaml文件中的dependencies中加入ffipath

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 World\n");
}
复制代码

sample.def中简单导出

代码语言:javascript
复制
LIBRARY   sample
EXPORTS
   sample
复制代码

写编译使用的CMakeLists.txt文件

代码语言:javascript
复制
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编译

代码语言:javascript
复制
cd library/build
cmake ..
make
复制代码

如果在library/build文件夹下生成了libsample.1.0.0.dylib文件,那么说明编译成功了。

4. 写Dart通信代码

bin/main.dart中调用C

代码语言:javascript
复制
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地址

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 是什么
  • 解决的问题
  • 简单使用
    • 1. 创建项目
      • 2. pubspec.yaml引入FFI
        • 3. 编译C代码
          • 3. 编译C文件
            • 4. 写Dart通信代码
              • 5. 运行代码
              • 总结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档