# MoonBind 0.3：C 适配层与升级检查

0.3 将简单结构体按值调用、静态内联函数、解析诊断和升级检查接到同一条生成流程。普通绑定仍保留 0.2 的配置、修改保护、函数筛选、重命名和 `--check`。

## 生成 C 适配层

在仓库根目录执行：

```sh
moon run cmd/main --target wasm-gc -- --config moonbind.bridge.json
moon run cmd/main --target wasm-gc -- --config moonbind.bridge.json --check
```

也可直接指定头文件：

```sh
moon run cmd/main --target wasm-gc -- testdata/bridge/point.h --bridge --strict --out _build/point-bridge --target x86_64 --json
```

`--bridge` 在 `bindings.mbt`、`strings.mbt`、`stub.c`、`moon.pkg`、`moonbind-report.json` 之外生成 `bridge.c`。将生成包放入 MoonBit 项目，在 native 目标下编译。外部函数的实现仍需通过 `--native-source` 或消费项目的链接配置提供；头文件内的静态函数由 C 编译器编入适配层。

支持范围：

- 有符号/无符号 32、64 位整数，float、double，以及 void 返回值。
- 完整、有名称、字段为上述标量的简单 struct，包括解析器可命名的匿名 typedef struct。
- 这些类型组成的外部函数及带函数体的 static/static inline 函数。
- 结构体参数改为借用指针，由 C 包装函数解引用后按值调用原函数；结构体返回值分配为句柄。

不支持的桥接输入会列入跳过报告；`--strict` 要求所选函数全部得到支持。指针参数、回调、变参、union、数组/指针/嵌套字段、位域、窄整数以及 packed/aligned 记录暂不在桥接范围内。普通绑定模式仍可处理其既有指针接口。原始函数名 `mb_` 和 `moonbind_bridge_` 前缀保留给适配层。

对于示例中的 `struct Point { int x; int y; }`，生成的接口包括：

```moonbit
let a = @point.mb_Point_new(3, 4)
let b = @point.mb_Point_new(10, 20)
assert_false(a.is_null())
assert_false(b.is_null())
let sum = @point.point_add(a, b)
assert_false(sum.is_null())
assert_eq(@point.mb_Point_get_x(sum), 13)
assert_eq(@point.point_sum(sum), 37)
@point.mb_Point_free(sum)
@point.mb_Point_free(a)
@point.mb_Point_free(b)
```

`*_new` 和结构体返回包装函数分配内存，失败返回空句柄。调用方必须检查 `is_null()`，使用后恰好释放一次。输入句柄为借用，不会被包装函数释放。不得使用已释放句柄。字段操作和按值调用收到空输入时终止进程；这不是自动所有权或生命周期管理。

适配层包含原始头文件，并生成指针/long 宽度、结构体大小、对齐和字段偏移的 C11 静态断言。这些检查在 **C 编译时** 执行。生成报告只记录 `checks_emitted_not_executed`，不会把尚未编译运行的产物声称为已验证。

头文件和包含路径会解析成绝对路径；移动项目或切换机器后需要重新生成。解析和编译时须使用一致的宏、头文件版本和 ABI。编译器的内置宏与 MoonBind 的预处理环境不完全等价；静态断言也不证明所有函数签名、语义及所有权均兼容。

## 解析诊断与严格模式

解析诊断包含文件、行、列、token、代码和说明。预处理诊断也会阻止生成；其结构化位置暂指向入口文件第一行，具体包含文件信息保留在 message 中。当前明确报告部分未知声明、缺失分隔符，以及 complex、128 位整数、long double、atomic、汇编符号别名和若干 ABI 属性等不支持的语法。

```sh
moon run cmd/main --target wasm-gc -- testdata/bridge/unsupported.h --json
moon run cmd/main --target wasm-gc -- testdata/bridge/unsupported.h --strict --json
```

非严格报告模式允许输出 `status: incomplete` 以供排查；存在诊断时生成代码和 `--verify` 都拒绝继续。严格模式还拒绝跳过所选函数。它不是完整 C 编译器，不验证函数体语义，也不保证发现全部扩展语法。通过库 API 直接使用 AST 时，应自行检查 `diagnostics`；旧的 `codegen.generate` 仍是低层接口。

## API 升级规则与离线报告

```sh
moon run cmd/main --target wasm-gc -- testdata/bridge/point-v2.h --compare testdata/bridge/point.h --fail-on changed --html > upgrade-review.html
```

退出码 **3** 表示规则阻止通过，HTML/JSON 报告仍正常输出，CI 应保留报告。退出码 1 表示运行失败，2 表示命令行参数错误。不要在 CI 中无条件忽略非零退出码。

| `--fail-on` | 阻止通过的条件 |
| --- | --- |
| `none`（默认） | 只生成报告 |
| `removed` | 删除声明，或解析存在已知诊断 |
| `changed` | 修改/删除声明，或解析存在已知诊断 |
| `any` | 新增/修改/删除声明，或解析存在已知诊断 |

HTML 包含变化前后内容、受影响函数、调用上下文及原始报告；不依赖网络、不执行脚本，并转义头文件提供的文本。静态函数也参与声明对比，其绑定状态为 `requires_bridge`。函数体内部实现变化不在对比范围内；这是源码声明审查，不是二进制兼容性结论。

配置支持 `strict`、`bridge` 和 `fail_on`。比较模式会忽略配置中的输出目录及 bridge 开关，但保留解析上下文。

## 迁移与验证

- 已有依赖用 `moon add --upgrade icyaaaww/moonbind@0.3.0` 更新，新项目可用 `moon add icyaaaww/moonbind@0.3.0`。
- 0.2 的五文件管理状态可迁移到 0.3 的六文件状态；仍检测用户修改并在写入前拒绝冲突。普通模式生成的 `bridge.c` 是不参与编译的占位注释。
- `CModule` 新增 `diagnostics`、`static_definitions`；`Options` 新增四个选项字段。手工完整构造这些公开结构的调用方需要补齐字段；建议使用构造器/参数解析接口。
- `codegen.generate_bridge` 返回绑定文本、C 源码、已适配函数、记录及跳过原因。
- `python scripts/verify-v03.py` 检查严格诊断、禁止危险输出、退出码、离线 HTML 与可重复生成。
- Linux 上的 `python scripts/verify-v03.py --native` 新建消费项目，编译链接并运行生成接口；另外用 ASan/UBSan 执行 C 包装层的 1,000 次分配/使用/释放，并故意修改头文件，验证布局断言阻止编译。
- 消毒器检查覆盖测试夹具的 C 包装层，不等于所有生成项目或整个 MoonBit 运行时的内存安全证明。SQLite/zlib（Z_SOLO 头文件配置下的 adler32）原生回归和三种 ABI 的 clang 布局对照继续保留。
