contributor-context
Contributor context for coding agents working in this repository. Human contributors should start with `README.md` and…
<!-- GENERATED from docs/api/cpp-binding-rules.md by scripts/build-agent-skill.mjs. Do not edit. -->
$ npx -y skills add crossbind/crossbind --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
<!-- GENERATED from docs/api/cpp-binding-rules.md by scripts/build-agent-skill.mjs. Do not edit. -->
<!-- GENERATED from docs/api/cpp-binding-rules.md by scripts/build-agent-skill.mjs. Do not edit. -->
> crossbind generates JS bindings automatically. There are no `EMSCRIPTEN_BINDINGS` macros to hand-write. But the generator only handles a constrained subset of C++. Stay inside that subset and you get binding-for-free; step outside and you'll need a wrapper or a SWIG escape (`swig-escape.md`).
This doc tells you the rules. **For the canonical type table** (which JS type maps to which C++ type, with `toArray`/`toVector` examples), use the website:
This page covers what the website doesn't: the **rules** an agent must follow when writing C++ that crossbind will bind.
Raw pointers bind. What the generator cannot turn into an object crosses as a `NativePointer` handle: an opaque JS object that carries the address and owns whatever crossbind allocated for it.
| C++ | JS | |---|---| | `const char *` parameter | `string`, a handle, or `null` | | `const char *` return or callback argument without a following integer | `string` or `null` | | `const char *` callback argument immediately followed by an integer | handle or `null`; read with `readBuffer(pointer, length)` | | `char *`, `unsigned char *`, `void *`, `T **`, pointers to numbers, enums or types the bridge does not know | handle | | `T *` returning a class the bridge knows | instance | | `T *` parameter of a struct the imported header defines, `extern "C"` or not | instance | | `T *` parameter of a struct the bridge only sees declared (`sqlite3`, `PJ`) | handle | | `T *` field of a struct | reads as an instance when `T` is a struct the same header binds, otherwise as a handle; takes either, or `null` | | `int &`, `double &`, `std::string &` out-parameters | handle from `allocPointer` / `allocString`, read back afterwards | | function pointer parameter or field | a JS function, a handle another binding returned, or `null`; a field reads as a handle | | other pointer argument inside a callback | always a handle |
Every module that binds a pointer also exports the helpers: `cstring(text)` and `readCString(handle)`, `allocBuffer(bytes)`, `allocPointer(count)` (both zero-filled), `allocString(text)` and `readString(handle)`, `readNumberAt(handle, index, kind)` / `writeNumberAt(handle, index, kind, value)` with kinds `int8` … `uint64`, `float32`, `float64`, `readPointerAt` / `writePointerAt`, `readBytes(handle, length)` / `writeBytes(handle, u16string)` with one byte per character, `readBuffer(handle, length)` returning a `Uint8Array` copy / `writeBuffer(handle, bytes)` copying any `ArrayBuffer` or view of one (a `Uint8Array`, a Node `Buffer`), and `releaseCallback(fn)` to free a callback slot.
void process(int* data, size_t len); // handle in, e.g. from allocBuffer char* getName(); // handle out: read it, then free it the library's way int parse(const char* text); // takes a JS string size_t encode(unsigned char* out, size_t cap); // bytes out through a buffer
const data = allocBuffer(3 * 4);
[7, 8, 9].forEach((n, i) => writeNumberAt(data, i, 'int32', n));
process(data, 3);
const name = readCString(getName());
parse('x=1');
const out = allocBuffer(1024);
const bytes = readBuffer(out, encode(out, 1024)); // Uint8ArrayOnly the const form converts: C APIs copy a `const char *` input, while a `char *` result is memory the library handed over, so it stays a handle you read and free explicitly. On worker-backed browser builds handles and instances are proxies, `instanceof NativePointer` holds only on direct runtimes, and JS functions cannot cross into a worker.
A string passed for a `const char *` is a copy that lives for the call. When C keeps the pointer afterwards (`sqlite3_bind_text` with `SQLITE_STATIC`), pass a `cstring` handle and keep it until C is done with it, or let C take its own copy (`SQLITE_TRANSIENT`).
A callback's `const char *` followed by an integer may describe bytes with embedded NULs or no terminator. It stays a handle, so Expat's character-data handler can read exactly `readBuffer(text, length)`. If that integer is a status rather than a length and the library guarantees a terminated string, use `readCString(text)`. Read the data while the callback runs; the handle does not keep the library's buffer alive.
Integer and enum parameters take numbers. An enum parameter also takes a member (`await Mode.Fast`), an integer parameter takes an enum member as its value, and a `char` parameter takes a one-character string as its code; anything else throws a `TypeError` instead of crossing as 0. A 64-bit integer (`int64_t`, `long long`, and on React Native also `long` and `size_t`) crosses as a BigInt and takes a BigInt or a safe-integer Number; on wasm32 `long` and `size_t` are 32-bit Numbers.
Build defaults assume modern C++. Use:
Runtime notes from the cross-runtime conformance suite: a vector PARAMETER takes a vector instance, which `Module.toVector` builds. A wasm build also takes a plain JS array: for every vector parameter in worker mode, and for a module function's or constructor's in direct mode. By-value `std::vector` RETURNS are real vector proxies on direct runtimes (wasm and jsi), freed like any value JS owns (`lifecycle-and-types.md`), and arrive as plain JS arrays on worker-backed runtimes - that array conversion is the worker contract (`Module.toArray` a
Import C++ and Rust like JavaScript modules (WebAssembly & React Native)
Contributor context for coding agents working in this repository. Human contributors should start with `README.md` and…
<!-- GENERATED from docs/api/app.md by scripts/build-agent-skill.mjs. Do not edit. -->
<!-- GENERATED from docs/api/build-state.md by scripts/build-agent-skill.mjs. Do not edit. -->
<!-- GENERATED from docs/api/conan.md by scripts/build-agent-skill.mjs. Do not edit. -->
<!-- GENERATED from docs/api/crossbind-build.md by scripts/build-agent-skill.mjs. Do not edit. -->