Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

C ABI guide — libair-base.so (overview)

Audience: C developers (and, eventually, Swift / Python / Ruby via bindings) consuming Air without writing Rust. These pages explain how to use the library and what obligations fall on the caller — not just what to call.

air-base-capi exposes the layer-1 air-base-lib (pure Rust) as a stable C ABI, producing libair-base.so. This is the project’s first C-ABI pass: the proving ground for the methodology of the whole future “Air libc” (Rust userland, redrawn contracts, explicit memory ownership). Contract decisions:

  • Single source of truth: per-symbol docs are born from the Rust /// comments, carried by cbindgen into the committed header include/air_base.h, then rendered by Doxygen (HTML + man pages). No hand-written C docs, hence zero drift (ADR-027).
  • Stability: the header is a C-ABI contract guaranteed for 10 years, committed and diffed in CI (ADR-012).
  • Errors: AirStatus returned in-band, no errno, panic = "abort" (ADR-045).

Why a C ABI, not just Rust

Rust is the implementation; the C ABI is the universal contract. Every language can call C. By freezing the boundary in C — #[repr(C)] types, in-band status, explicit ownership — Air becomes polyglot from day one without maintaining N parallel docs: one header, one set of guarantees.

The pages in this guide

  1. Getting started — include the header, link the lib, versioning/ABI.
  2. Error model (AirStatus) — test, read, propagate; why no panic crosses the ABI; why no errno.
  3. Memory ownership & lifecyclethe critical point: who allocates, who frees, with which function. Per-symbol table.
  4. Thread-safety by type — what is callable from which thread, with concrete pitfalls.
  5. Compilable C examples — UUID, logging, time measurement, compiled against the committed header.

The three rules to remember above all

  1. Check every return. Every function returns an AirStatus (or a non-NULL pointer for air_status_message). An *out is written only on AIR_STATUS_OK. See Error model.
  2. Uniform ownership rule: +1 on RETURN, +0 on ARGUMENT. A returned handle (air_log_open, air_log_fields_new) is owned by the caller → you must free it. A type passed as an argument is borrowed → the callee neither frees it nor retains it. See Memory ownership.
  3. String outputs use YOUR buffer. No string is allocated by Air in T1/T3: you provide the buffer (sizes AIR_UUID_HYPHENATED_LEN / AIR_ID128_HEX_LEN); too small ⇒ AIR_STATUS_BUFFER_TOO_SMALL (never silent truncation). Nothing to free.

Version française : voir Guide ABI C — vue d’ensemble.