aimux-ffi 0.5.0

C ABI boundary for aimux multi-language bindings (opaque handle + push stream)
Documentation

aimux-ffi: C ABI for multi-language bindings.

Provides an opaque handle registry + JSON wire format + push callback stream. The C ABI is consumed by C/C++, Go, Kotlin, Java, Swift, and Flutter. Native bindings (Python / Node) bypass this layer and use aimux-providers directly.

Errors

Every fallible C function returns *mut aimux_error_t: NULL on success (the result is written to the out-parameter), a heap-owned error value on failure (the out-parameter is left at its sentinel: handle 0, pointer NULL). Every non-NULL error has one code from [aimux_error_code] and one message from [aimux_error_message], and is released exactly once with [aimux_error_free]. Codes 1..17 come from AiMuxError, 100..105 from RecordingError, and 200..206 identify failures detected while crossing the C ABI.

Memory ownership

  • Every function returning *mut c_char — error getters included — transfers ownership to the caller, who MUST free it with [aimux_free_string]. Handles (u64) are released with [aimux_drop_handle].
  • [aimux_stream_text] callbacks receive *const c_char pointers that are valid only for the duration of the callback. The callback must copy the data synchronously; the backing buffer is freed when the callback returns.

Concurrency

All async provider work runs on a shared multi-threaded tokio runtime. The C ABI functions are synchronous: they block_on the runtime until the operation completes. Callbacks execute on the same thread/call-stack that invoked the FFI function, so they must not re-enter the FFI layer: a nested block_on on the same thread makes tokio panic ("Cannot start a runtime from within a runtime"). Rust's non-unwind extern "C" ABI does not allow a panic to propagate — the process terminates (and under this workspace's release profile, panic = "abort", it terminates at the panic site). Either way the re-entrant call must be rejected before it reaches the runtime; the thread-local guard in ffi_block_on does that (issue M7).