# MoonBind 0.8：复杂调用契约与升级维护

0.8 面向 C 库接入中的输出参数、错误码、同步回调，以及升级后重新验证的工作。解析、布局、包装函数和 C 适配代码仍由 MoonBit 生成；Python 标准库驱动器负责编排、快照与报告。

## 一次跑通真实 SQLite 回调

```sh
moon update
python moonbind.py init ../my-query --template sqlite-callback
python moonbind.py validate ../my-query
python moonbind.py report-check ../my-query
```

模板携带已有 SQLite 源码与许可，生成 `sqlite3_open_checked`、`sqlite3_prepare_v2_checked`、`sqlite3_close_checked` 和 `sqlite3_exec_sync`。无需为这些接口手写 C 包装。示例断言三次行回调、复制后的 11/22/33 文本值、SQL NULL、列数、错误中止、MoonBit 抛错、非法 SQL 和预处理查询值。旧 SQLite 模板保留 `SQLITE_TRANSIENT` 文本生命周期适配，不宣称自动推断此类库约定。

## 配置契约

```json
{
  "header": "vendor/sqlite3.h",
  "out": "bindings",
  "target": "win64",
  "strict": true,
  "native_sources": ["library.c"],
  "allow_functions": ["sqlite3_open", "sqlite3_close", "sqlite3_exec"],
  "status_codes": {"sqlite3_open": "0", "sqlite3_close": "0"},
  "out_params": {"sqlite3_open": "ppDb"},
  "null_params": {"sqlite3_exec": "errmsg"},
  "callbacks": {"sqlite3_exec": "callback:#3:1"},
  "trace_calls": true
}
```

`#3` 是从 0 开始的参数位置，用于原头文件没有形参名的场景。有形参名时优先使用名字。状态码写成字符串，范围为有符号 32 位；不推测宏名称或所有权。

| 配置 | 生成行为 |
| --- | --- |
| `status_codes: {fn: "0"}` | `fn_checked` 返回 `Result[Unit, Int]`，指定值为成功 |
| `out_params: {fn: "output"}` | 单个 `T**` 输出槽；须同时配置状态码；成功返回 `Ok(Handle?)`，失败返回 `Err((code, Handle?))` |
| `null_params: {fn: "tail,optional"}` | 去掉列出的指针形参，由独立 FFI 声明传入真正的 NULL；可与输出或回调组合 |
| `ownership: {create: "close:0"}` | 创建者直接返回非字节指针，释放函数返回 signed int；检查释放结果 |
| `callbacks: {fn: "cb:context:1"}` | `fn_sync` 接受 MoonBit 闭包，生成 C 上下文转接；1 为回调抛错时交还 C 的返回码 |
| `trace_calls: true` | 生成可选的 C 入口记录，验证报告汇总实际进入适配函数的次数 |

输出错误分支保留句柄，因为部分库在失败时也分配资源。调用方必须按库文档释放错误句柄。成功但 NULL 不擅自改判为错误。作用域释放失败抛出 `CleanupFailed(code)`；业务回调与释放都失败时抛出 `CleanupDuringError(code, original_error)`。释放函数可能在报错时仍保持资源存活，生成器不会重试或推测释放是否成功；需要重试/接管资源的接口应使用原始句柄与显式关闭逻辑。

旧的 `ownership`、`buffers` 和 `copy_strings` 保留。所有无效新契约即使关闭 strict 也会拒绝写入。新契约用于普通绑定模式；结构体桥接模式保留原有支持。

## 同步回调支持边界

- 回调必须返回 C `int`，第一个参数是 `void*` 上下文；其他回调参数支持 32/64 位整数、浮点和借用指针。
- 外层 C 函数返回 signed int 状态，并有独立的回调参数和 `void*` 参数；C 必须在本次调用期间、同一线程调用，不得保存回调/上下文。
- 闭包可捕获 MoonBit 状态。C 转接器为每次回调增加上下文引用，MoonBit 回调消费该引用，外层调用持有借用生命周期；允许递归进入另一次同步调用。
- MoonBit 错误先保存在上下文，回调返回用户指定的中止码；外层 C 返回后重新抛出原错误。C 若继续回调，只返回中止码，不再执行用户闭包。若 C 永远不返回，包装无法使它强制结束。
- 回调收到的 C 指针只在库声明的借用期有效，不能任意保存。不支持跨线程、异步保留、变参、结构体按值回调，也不保证进程崩溃后的清理。
- `callbacks` 可与 `null_params` 组合；0.8 不与 `status_codes/out_params` 在同一函数上组合。

`copy_cstr_array(ptr, count)` 可在回调借用期内复制 C `char**`。SQLite 示例直接使用回调列数读取结果，NULL 元素保留为 `None`；调用方必须保证 count 不超过实际数组长度。这不是任意指针的内存检查器。

## 调用证据

`validate` 为每个运行检查创建独立的记录文件，传入 `MOONBIND_TRACE`，汇总 `adapter_entries`。原始和 checked 调用都经过配置的 C 适配函数；sync 调用只记录一次外层 C 函数入口。**一次入口不代表函数返回成功，也不等于断言覆盖充分**。

报告分别呈现作者声明的检查关联、进程断言是否通过、实际 C 适配入口次数。未开启记录时次数为 0，运行检查的 `trace_enabled` 为 false；不能据此推断未调用。记录是单线程调试证据，未签名、不防篡改，不跟踪库内部调用或用户另写的绑定。文件写入失败可能造成记录不完整。生产接入可关闭 `trace_calls` 避免文件 I/O 开销。

## 升级工作流

```sh
python moonbind.py upgrade ../my-query --against ../old-version/sqlite3.h
```

输出 `reports/upgrade.json` 与离线 HTML，列出变动函数、关联契约和运行检查。临时目录生成验证检查当前契约是否仍有效，原有绑定与配置不被覆写。有影响或无效契约时退出码为 **3**；解析或执行失败为 **1**；未变化为 **0**。旧头文件的传递包含文件必须保持可访问；比较采用当前宏、包含路径和 ABI，无法推断同签名下的语义或生命周期变化。

```sh
python moonbind.py install --bin D:/Codex/bin
# Linux/macOS example: --bin ~/.local/bin
```

生成 `moonbind.cmd` 或 `moonbind`，指向当前源码和 Python；将该目录加入 PATH 后可运行 `moonbind validate PROJECT`。保持源码目录不移动，或移动后重新安装入口。拒绝覆盖无关同名文件。不修改全局 PATH、不自动安装外部工具。

## 平台和验证

| 平台 | 原生工具链与范围 |
| --- | --- |
| Linux x86-64 | LP64，C11 clang；保留旧版真实库/布局回归 |
| macOS ARM64 | LP64，Apple clang；同一消费项目验证脚本 |
| Windows x64 | LLP64，MSVC Build Tools + Windows SDK；自动发现编译环境；long=4、pointer=8 |

Windows 限普通记录；CLI 拒绝位域、packed/aligned、空记录和超出 signed int 的枚举。MSVC x64 的 `__cdecl/__stdcall` 按统一 x64 调用约定处理，其他 ABI 不移除这些关键字。`__vectorcall` 等约定不在支持范围。zlib 模板仍仅在 Linux/macOS 验证；Windows 需另外配置 zlib 链接。

```sh
moon test --target wasm-gc
python scripts/verify-v08.py
python scripts/verify-v05.py
```

0.8 脚本运行 calls、sqlite-callback、contracts、nested、cjson 五套原生项目；包括 10,000 次回调、重入、延迟抛错、成功/错误输出句柄、双重错误、准确入口次数、独立 C ABI 静态断言、迁移、升级不覆写、断言失败使报告失效与可选记录关闭。CI 配置覆盖 Linux/macOS/Windows；是否通过以对应提交的 CI 结果为准，本地 Windows 结果不能代替另两平台结果。

真实用户试用仍未完成，参见 [试用方案](user-trial.md)。不把作者运行与自动化测试计作独立用户反馈。

## API 迁移

`Options` 新增 `status_codes/out_params/null_params/callbacks/trace_calls`，完全手工构造者需要补齐；`Abi` 新增 `Win64`，穷尽匹配需处理新分支。`generate` 新增可选参数，已有调用可保持原样。新增 `call_adapters` 用于需要直接使用生成器包的工具作者；使用高级 CLI 可确保先做契约检查。
