Make MoonBit C Bindings
Use this skill for end-to-end binding projects. Also read moonbit-c-binding
before implementation for low-level FFI syntax, ownership annotations, and
moonbit.h details.
Quick Start
- Clone or inspect the upstream C/C++ project in a temporary directory.
- Identify the public header(s), generated config headers, source layout,
allocator API, and build-time type widths.
- Decide the safe MoonBit API surface; do not mechanically expose every C API.
- Vendor sources with
templates/prepare.py or link to a system library only
when that is explicitly desired.
- Write a thin C wrapper, private MoonBit externs, and safe public MoonBit
wrappers.
- Validate with
moon check, native tests, ASan, moon info, and vendoring
script idempotency.
Binding Architecture
Prefer this layout, adapting names to the library. Start from bundled templates
instead of rewriting scaffolding from scratch:
scripts/prepare.py # optional: pinned upstream download + generated stubs
moon.mod.json # preferred/supported native targets
src/moon.pkg # native-stub list and file target gates
src/wrapper.c # ABI normalization and ownership boundaries
src/ffi.mbt # private extern "c" declarations
src/<domain>.mbt # safe public MoonBit API
src/<domain>_test.mbt # regression tests
src/README.mbt.md # tested documentation examples
README.md -> src/README.mbt.md
Template mapping:
templates/prepare.py -> scripts/prepare.py
templates/moon.mod.json -> moon.mod.json
templates/moon.pkg -> src/moon.pkg
templates/wrapper.c -> src/wrapper.c
templates/ffi.mbt -> src/ffi.mbt
templates/api.mbt -> src/<domain>.mbt
templates/README.mbt.md -> src/README.mbt.md
For ASan validation, copy or invoke the companion runner from
moonbit-c-binding/scripts/run-asan.py as scripts/run-asan.py; do not invent
a new ASan patching script unless that runner cannot fit the project.
Workflow
1. Survey Upstream
- Read public headers first; they define the binding contract.
- Record configured widths for project-specific typedefs: index types, scalar
types, size/count types, handle types, enum backing types, and callbacks.
- Separate library APIs from CLI-only, internal, generated, or test code.
- Look for functions that allocate memory, mutate inputs, store callbacks, or
require paired
destroy/free calls.
2. Design The MoonBit API
- Expose domain-specific MoonBit types that match the current C library instead
of raw pointers and arrays where possible.
- Validate shapes and option lengths before entering C.
- Omit unsafe or misleading C features when the safe wrapper cannot uphold
their semantics.
- Map C status codes into MoonBit errors; return structured result records for
output parameters.
3. Vendor Or Link
- For portable packages, vendor C sources into
native-stub with a pinned
revision and a repeatable script.
- Flatten sources if MoonBit requires stubs in one package directory, and
rewrite includes deterministically.
- Generate configured headers instead of relying on ad hoc compiler flags.
- Ensure the vendoring script can be rerun with no tracked diff.
4. Build The FFI Boundary
- C wrapper owns ABI normalization: type-width assertions, optional pointer
conversion, output copying, and freeing C-allocated memory.
ffi.mbt should keep externs private and use #borrow / #owned explicitly.
- Public MoonBit files should call only safe wrapper functions, never raw C APIs.
- Avoid extra Boolean sentinel parameters for optional arrays; prefer empty
MoonBit arrays and check
Moonbit_array_length in C.
5. Validate
Run, at minimum:
moon fmt
moon check --target all --warn-list +73
moon test --target native
python3 scripts/run-asan.py
moon info --target native
python3 scripts/prepare.py
git status --short
For native-only packages, set "preferred-target": "native" and
the smallest true "supported-targets" value in moon.mod.json.
Required References
Lifecycle And Ownership;
Vendoring And Package Setup;
Testing And Documentation.
1---2name: make-moonbit-c-bindings3description: Guides agents through complete, maintainable MoonBit bindings for C/C++ libraries, from upstream source survey through vendoring, safe API design, documentation tests, and ASan validation. Use when creating or hardening MoonBit native FFI bindings, wrapping C APIs, vendoring C sources into native-stub, or turning a C library into a MoonBit package.4---56# Make MoonBit C Bindings78Use this skill for end-to-end binding projects. Also read `moonbit-c-binding`9before implementation for low-level FFI syntax, ownership annotations, and10`moonbit.h` details.1112## Quick Start131. Clone or inspect the upstream C/C++ project in a temporary directory.142. Identify the public header(s), generated config headers, source layout,15 allocator API, and build-time type widths.163. Decide the safe MoonBit API surface; do not mechanically expose every C API.174. Vendor sources with `templates/prepare.py` or link to a system library only18 when that is explicitly desired.195. Write a thin C wrapper, private MoonBit externs, and safe public MoonBit20 wrappers.216. Validate with `moon check`, native tests, ASan, `moon info`, and vendoring22 script idempotency.2324## Binding Architecture2526Prefer this layout, adapting names to the library. Start from bundled templates27instead of rewriting scaffolding from scratch:2829```text30scripts/prepare.py # optional: pinned upstream download + generated stubs31moon.mod.json # preferred/supported native targets32src/moon.pkg # native-stub list and file target gates33src/wrapper.c # ABI normalization and ownership boundaries34src/ffi.mbt # private extern "c" declarations35src/<domain>.mbt # safe public MoonBit API36src/<domain>_test.mbt # regression tests37src/README.mbt.md # tested documentation examples38README.md -> src/README.mbt.md39```4041Template mapping:42- `templates/prepare.py` -> `scripts/prepare.py`43- `templates/moon.mod.json` -> `moon.mod.json`44- `templates/moon.pkg` -> `src/moon.pkg`45- `templates/wrapper.c` -> `src/wrapper.c`46- `templates/ffi.mbt` -> `src/ffi.mbt`47- `templates/api.mbt` -> `src/<domain>.mbt`48- `templates/README.mbt.md` -> `src/README.mbt.md`4950For ASan validation, copy or invoke the companion runner from51`moonbit-c-binding/scripts/run-asan.py` as `scripts/run-asan.py`; do not invent52a new ASan patching script unless that runner cannot fit the project.5354## Workflow5556### 1. Survey Upstream5758- Read public headers first; they define the binding contract.59- Record configured widths for project-specific typedefs: index types, scalar60 types, size/count types, handle types, enum backing types, and callbacks.61- Separate library APIs from CLI-only, internal, generated, or test code.62- Look for functions that allocate memory, mutate inputs, store callbacks, or63 require paired `destroy/free` calls.6465### 2. Design The MoonBit API6667- Expose domain-specific MoonBit types that match the current C library instead68 of raw pointers and arrays where possible.69- Validate shapes and option lengths before entering C.70- Omit unsafe or misleading C features when the safe wrapper cannot uphold71 their semantics.72- Map C status codes into MoonBit errors; return structured result records for73 output parameters.7475### 3. Vendor Or Link7677- For portable packages, vendor C sources into `native-stub` with a pinned78 revision and a repeatable script.79- Flatten sources if MoonBit requires stubs in one package directory, and80 rewrite includes deterministically.81- Generate configured headers instead of relying on ad hoc compiler flags.82- Ensure the vendoring script can be rerun with no tracked diff.8384### 4. Build The FFI Boundary8586- C wrapper owns ABI normalization: type-width assertions, optional pointer87 conversion, output copying, and freeing C-allocated memory.88- `ffi.mbt` should keep externs private and use `#borrow` / `#owned` explicitly.89- Public MoonBit files should call only safe wrapper functions, never raw C APIs.90- Avoid extra Boolean sentinel parameters for optional arrays; prefer empty91 MoonBit arrays and check `Moonbit_array_length` in C.9293### 5. Validate9495Run, at minimum:9697```bash98moon fmt99moon check --target all --warn-list +73100moon test --target native101python3 scripts/run-asan.py102moon info --target native103python3 scripts/prepare.py104git status --short105```106107For native-only packages, set `"preferred-target": "native"` and108the smallest true `"supported-targets"` value in `moon.mod.json`.109110## Required References111[Lifecycle And Ownership](references/lifecycle-and-ownership.md);112[Vendoring And Package Setup](references/vendoring-and-package-setup.md);113[Testing And Documentation](references/testing-and-documentation.md).