docs/ffigen.md
2024-10-18 10:20:13 +08:00

2.5 KiB
Raw Permalink Blame History

ffigen

源文件代码如下

#ifndef HELLO_H
#define HELLO_H
#include "ppp.h" // 为了使用struct Point
#include <stdio.h> // 标准库文件

void hello();
void say_hello(const char* name);
void say_hello2(struct Point* p);


#endif	

只想生成当前文件下的函数声明,而不生成有关标准库里面的内容

# pubsspey.yaml
headers:
    entry-points:
      - "clibrary/hello.h"
    include-directives:
      - "**hello.h"  # 使用相对路径不管用
      

生成出来的dart代码没有标准库中的符号。

但是自动生成ppp.h中有关struct Point 结构体的相关内容say_hello2函数参数用到了

class Point extends ffi.Struct {
  @ffi.Int32()
  external int TID;
  @ffi.Int32()
  external int type;
  @ffi.Int32()
  ......
}

如果不关心结构体具体内容

# pubsspey.yaml
structs:
    dependency-only: opaque

生成的代码如下

class Point extends ffi.Opaque {} // error 需要手动修改
// 修改后
final class Point extends ffi.Opaque {}

ffi生成的class 有错误 需要手动更改

final class Point extends ffi.Struct {
  @ffi.Int32()
  external int x;
} // 正确
class Point extends ffi.Struct {
  @ffi.Int32()
  external int x;
}// 错误缺少final ffigen自动生成的

未避免每次生成都需要手动更改 解决方案第一次通过ffi生成后将class复制到另外一个文件中 bindings.dart。但是生成的dart代码中找不到Point类型需要引入bindings.dart这个文件。于是需要进行配置

使生成的代码自动引入class所在的dart文件

library-imports:
    point: 'bindings.dart' # @1 point需要引入dart文件也可以引入其他package bindings存放了class Point
  type-map:
    'structs': # Point是结构体.
      'Point': # 依赖的C语言中的结构体名称
        'lib': 'point' # @1 名字自定义 
        'c-type': 'Point' # import 'bindings.dart' as point   ffi.Pointer<point.Point> // point文件中具体要使用的类型
        'dart-type': 'point'
import 'bindings.dart' as point // @1;
......

  void say_hello2(
    ffi.Pointer<point.Point> p,
  ) {
    return _say_hello2(
      p,
    );
  }

  late final _say_hello2Ptr =
      _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<point.Point>)>>(
          'say_hello2');
  late final _say_hello2 =
      _say_hello2Ptr.asFunction<void Function(ffi.Pointer<point.Point>)>();

生成的代码中既没有错误的class Point 也不需要手动引入正确的dart Point类