graph-lite.h is the contract every binding pins. Design the whole C surface deliberately, once, before the model lands on top of it — a C ABI retrofitted onto a C++-shaped design is a second, worse API wrapping the first.
See ADR 0004.
Done when
- Opaque handles for the store and for any cursor. No published struct layout — layout in a public header is an ABI promise nobody wants to keep.
- Fixed-width integer node/edge ids. The width is ABI: a binding that read 64 bits and now reads 32 does not fail to compile, it reads garbage.
- Buffer ownership is explicit — caller-owned with a size, or paired with a
graph_lite_free_*. A binding cannot free a pointer a different allocator produced. GRAPH_LITE_ERR_BUFFER_TOO_SMALL reports the required size rather than truncating.
- No callback into the caller's runtime on a hot path. A GC'd runtime re-entering mid-traversal is how a binding deadlocks. Cursors, not visitor callbacks.
- Every failure a binding must distinguish has its own status code;
graph_lite_status_string() never returns NULL, including for a code from a newer header.
- The C test (
tests/graph-lite/c_abi_test.c) covers each new entry point.
Constraint
Additive only, from the first release. Changing an exported entry point breaks every binding silently, at load time.
graph-lite.his the contract every binding pins. Design the whole C surface deliberately, once, before the model lands on top of it — a C ABI retrofitted onto a C++-shaped design is a second, worse API wrapping the first.See ADR 0004.
Done when
graph_lite_free_*. A binding cannot free a pointer a different allocator produced.GRAPH_LITE_ERR_BUFFER_TOO_SMALLreports the required size rather than truncating.graph_lite_status_string()never returns NULL, including for a code from a newer header.tests/graph-lite/c_abi_test.c) covers each new entry point.Constraint
Additive only, from the first release. Changing an exported entry point breaks every binding silently, at load time.