120 lines
2.5 KiB
Markdown
120 lines
2.5 KiB
Markdown
|
# ffigen
|
|||
|
|
|||
|
源文件代码如下
|
|||
|
|
|||
|
```c
|
|||
|
#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
|
|||
|
```
|
|||
|
|
|||
|
只想生成当前文件下的函数声明,而不生成有关标准库里面的内容
|
|||
|
|
|||
|
```yaml
|
|||
|
# pubsspey.yaml
|
|||
|
headers:
|
|||
|
entry-points:
|
|||
|
- "clibrary/hello.h"
|
|||
|
include-directives:
|
|||
|
- "**hello.h" # 使用相对路径不管用
|
|||
|
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
生成出来的dart代码没有标准库中的符号。
|
|||
|
|
|||
|
但是自动生成ppp.h中有关struct Point 结构体的相关内容(say_hello2函数参数用到了)
|
|||
|
|
|||
|
```dart
|
|||
|
class Point extends ffi.Struct {
|
|||
|
@ffi.Int32()
|
|||
|
external int TID;
|
|||
|
@ffi.Int32()
|
|||
|
external int type;
|
|||
|
@ffi.Int32()
|
|||
|
......
|
|||
|
}
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
如果不关心结构体具体内容
|
|||
|
|
|||
|
```yaml
|
|||
|
# pubsspey.yaml
|
|||
|
structs:
|
|||
|
dependency-only: opaque
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
生成的代码如下
|
|||
|
|
|||
|
```dart
|
|||
|
class Point extends ffi.Opaque {} // error 需要手动修改
|
|||
|
// 修改后
|
|||
|
final class Point extends ffi.Opaque {}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ffi生成的class 有错误 需要手动更改
|
|||
|
|
|||
|
```dart
|
|||
|
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文件
|
|||
|
|
|||
|
```yaml
|
|||
|
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'
|
|||
|
```
|
|||
|
|
|||
|
```dart
|
|||
|
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类
|
|||
|
|