Flutter自动生成C代码绑定插件ffigen的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter自动生成C代码绑定插件ffigen的使用

简介

ffigen是一个用于生成FFI(Foreign Function Interface)绑定的工具,可以帮助开发者将C代码集成到Flutter应用程序中。它支持解析C头文件,并为这些头文件中的函数、结构体、枚举等元素生成Dart代码。需要注意的是,ffigen目前只支持解析C头文件,不支持C++头文件。

通过使用ffigen,你可以轻松地调用C语言编写的代码——或者任何编译成遵循C调用约定模块的语言代码,如Go或Rust。有关更多细节,请参阅Dart官方文档

此外,ffigen还实验性地支持调用ObjC和Swift代码;详情请见Dart官方文档

示例

假设有一个名为example.h的头文件,内容如下:

int sum(int a, int b);

接下来,你需要在pubspec.yaml中添加配置信息:

ffigen:
  output: 'generated_bindings.dart'
  headers:
    entry-points:
      - 'example.h'

执行命令dart run ffigen后,将会生成一个名为generated_bindings.dart的文件,其内容可能类似于:

import 'dart:ffi' as ffi;

class NativeLibrary {
  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) _lookup;
  
  NativeLibrary(ffi.DynamicLibrary dynamicLibrary)
      : _lookup = dynamicLibrary.lookup;

  NativeLibrary.fromLookup(
      ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) lookup)
      : _lookup = lookup;

  int sum(int a, int b) {
    return _sum(a, b);
  }

  late final _sumPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>>('sum');
  late final _sum = _sumPtr.asFunction<int Function(int, int)>();
}

使用步骤

  1. 在你的pubspec.yaml中添加ffigen作为开发依赖项(运行dart pub add -d ffigen)。
  2. 添加package:ffi作为依赖项(运行dart pub add ffi)。
  3. 安装LLVM(详见安装LLVM)。
  4. pubspec.yaml中提供配置信息或在一个自定义YAML文件中提供配置信息(详见配置)。
  5. 运行工具:dart run ffigen

安装LLVM

package:ffigen依赖于LLVM。按照以下方式安装LLVM(9+版本):

Linux

  • 使用apt-get安装libclangdev:sudo apt-get install libclang-dev
  • 或者使用dnf:sudo dnf install clang-devel

Windows

  1. 安装带有C++开发支持的Visual Studio。
  2. 安装LLVM或通过winget安装:winget install -e --id LLVM.LLVM

MacOS

  1. 安装Xcode。
  2. 安装Xcode命令行工具:xcode-select --install

配置

配置可以通过两种方式提供:

  1. 在项目的pubspec.yaml文件中,以ffigen键的形式提供。
  2. 在自定义YAML文件中提供,然后在运行时指定该文件:dart run ffigen --config config.yaml

以下是部分可用的配置选项:

Key Explanation Example
output (Required) 生成绑定的输出路径 output: 'generated_bindings.dart'
llvm-path 指向llvm文件夹的路径 llvm-path: '/usr/local/opt/llvm'
headers (Required) 头文件入口点和包含指令 headers:\n entry-points:\n - 'folder/**.h'\n include-directives:\n - '**index.h'

更多配置选项请参考配置章节。

常见问题解答

如何处理未命名的枚举?

未命名的枚举被单独处理,在unnamed-enums下生成为顶级常量。例如,要包括/排除/重命名未命名的枚举,可以这样做:

unnamed-enums:
  include:
    - 'CX_.*'
  exclude:
    - '.*Flag'
  rename:
    'CXType_(.*)': '$1'

如何处理意外的枚举值?

默认情况下,原生枚举会被转换为Dart枚举,并提供int get valuefromValue(int)方法。如果你希望避免因新添加的枚举值导致的问题,可以告诉ffigen将这些枚举作为整数生成:

enums:
  as-int:
    include:
      - MyIntegerEnum
      - '*IntegerEnum'
    exclude:
      - FakeIntegerEnum

为什么有些结构体/联合声明即使在配置中排除了仍然会生成?

当一个被排除的结构体/联合是其他包含声明的依赖项时,这就会发生。(依赖意味着一个结构体被函数传递/返回或成为另一个结构体的成员)

注意:如果你将structs.dependency-only设置为opaqueffigen会将这些结构体依赖项作为Opaque生成,前提是它们仅通过引用(指针)传递。

structs:
  dependency-only: opaque
unions:
  dependency-only: opaque

更多FAQ请参考常见问题解答章节。

示例项目

以上就是关于ffigen的基本介绍及使用方法,希望能帮助你顺利地将C代码集成到Flutter项目中。


更多关于Flutter自动生成C代码绑定插件ffigen的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自动生成C代码绑定插件ffigen的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用ffigen自动生成C代码绑定的示例。ffigen是一个Dart包,用于从C头文件生成Dart FFI绑定代码。这极大地简化了与本地C库的交互过程。

步骤 1: 设置Flutter项目

首先,确保你已经有一个Flutter项目。如果没有,可以使用以下命令创建一个新的Flutter项目:

flutter create my_ffigen_project
cd my_ffigen_project

步骤 2: 添加ffigen依赖

pubspec.yaml文件中添加ffigen依赖:

dependencies:
  flutter:
    sdk: flutter
  ffigen: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

步骤 3: 配置ffigen

在项目的根目录下创建一个名为ffigen_config.yaml的文件,这是ffigen的配置文件。以下是一个简单的配置示例:

name: 'my_bindings'
description: 'Bindings for my native library.'
output: 'lib/generated_bindings.dart'
headers:
  - 'path/to/your/c_header_file.h'  # 替换为你的C头文件路径

步骤 4: 创建C头文件

假设我们有一个简单的C库,其头文件内容如下(保存为native_lib.h):

#ifndef NATIVE_LIB_H
#define NATIVE_LIB_H

#ifdef __cplusplus
extern "C" {
#endif

int add(int a, int b);

#ifdef __cplusplus
}
#endif

#endif // NATIVE_LIB_H

并且对应的C实现文件(native_lib.c):

#include "native_lib.h"

int add(int a, int b) {
    return a + b;
}

将这些文件放在你的项目中的某个位置,比如ios/Classes/android/app/src/main/cpp/(具体取决于你的平台设置)。

步骤 5: 运行ffigen

在命令行中运行以下命令来生成Dart绑定代码:

flutter pub run ffigen

这将在lib/目录下生成一个名为generated_bindings.dart的文件。

步骤 6: 使用生成的绑定

现在你可以在Dart代码中使用这个生成的绑定来调用C函数。例如:

import 'package:flutter/material.dart';
import 'generated_bindings.dart';  // 导入生成的绑定文件

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('ffigen Example'),
        ),
        body: Center(
          child: Text('Result: ${add(3, 4)}'),  // 调用C函数
        ),
      ),
    );
  }
}

注意:确保你的C库在编译时被正确链接到你的Flutter应用中。这通常涉及到一些平台特定的配置,比如在iOS上使用Xcode或在Android上使用CMake。

额外注意事项

  • 对于iOS,你可能需要在Xcode项目中添加C源文件,并确保它们在Build Phases中被正确编译。
  • 对于Android,你可能需要在CMakeLists.txt中添加C源文件,并确保NDK配置正确。

通过上述步骤,你应该能够成功地在Flutter项目中使用ffigen自动生成C代码绑定。如果你遇到任何特定问题,请查阅ffigen的官方文档或相关社区资源。

回到顶部