Expand description
CbindgenBuilder — the C / cbindgen language adapter.
§Experimental API
This module is a proof of concept. Its Rust builder API may change in a minor release; do not rely on it as part of the stable 0.5 API.
A Prebindgen back-end that turns a “flat” #[prebindgen] library into a
Rust file suitable for cbindgen to
parse into a C header plus a static / dynamic library.
Items are opt-in: nothing is converted unless it is explicitly declared
with CbindgenBuilder::function / CbindgenBuilder::opaque_ptr /
CbindgenBuilder::data_struct / CbindgenBuilder::enum_type /
CbindgenBuilder::tagged_union. The C name of a declared
type’s generated destructor can be pinned by chaining CbindgenBuilder::base_name.
§C ABI conventions
-
Pointer struct (declared with
CbindgenBuilder::opaque_ptr): aBox-owned Rust value whose lifecycle is owned by the C side. The C typeTis opaque/incomplete and the handle is a bareT *=Box::into_raw. A typed<name>_drop(T *)destructor (running the RustDrop) is generated per handle. -
Data struct (declared with
CbindgenBuilder::data_struct): a by-value#[repr(C)]struct whose fields are mapped to C-ABI wire types (String→*mut c_char). No per-struct destructor — eachchar*field is released individually via theCbindgenBuilder::free_memory_function. -
Enum type (declared with
CbindgenBuilder::enum_type): a fieldless enum, mirrored as a#[repr(C)]enum that cbindgen renders as the C enum. Rust → C hands over the mirror directly (Rust only ever builds declared variants). C → Rust must not do the reverse: a Cenumis anintat the ABI, so materialising a caller-supplied discriminant as a Rust enum is undefined behaviour when it matches no variant — before anymatchcould check it. An enum parameter is therefore taken asMaybeUninit<mirror>— the same ABI and the same C spelling (cbindgen rendersMaybeUninit<T>asT), but legal to hold any bit pattern — and its rawc_intis validated against the mirror’s variants before the Rust value is built. An unmatched value is a fallible-input error (see below), so a function taking an enum by value needs either aResultreturn orCbindgenBuilder::panic. This relies on cbindgen’s C rendering; theC++language mode is not supported. -
Tagged union (declared with
CbindgenBuilder::tagged_union): a data-carrying enum crossing by value as a#[repr(C)]enum with payload variants, which cbindgen renders as a tag enum plus aunionof the variant bodies. When any variant’s payload wire owns memory, a typed<name>_dropfrees the active arm. Inbound it obeys the same rule as a plain enum, one level up: the mirror arrives asMaybeUninit<mirror>, its leadingc_inttag is range-checked against the variants, and only then is the valueassume_inited and matched. Every payload wire is bit-pattern-agnostic (a declaredenum_typepayload rides asMaybeUninittoo, and is validated by its own converter), so the tag is the sole obligation. The typed drop checks it as well and treats an out-of-range one as nothing to release. -
Direct
Stringoutput: a barechar *— amalloc’d, null-terminated raw block (no wrapper struct), freed via thefree_memory_function. -
CbindgenBuilder::free_memory_function: the single, type-agnostic raw memory freer (Cfree) for everychar*the layer hands out (string returns and data-structStringfields). It runs no destructor and needs no length. Required whenever such string memory is produced. -
Result<T, E>return lowers by the success wire kind:- pointer wire (opaque handle,
char*) →T f(<inputs>, E *e), where a NULL return signals error (details written to*e); - unit →
bool f(<inputs>, E *e); - value wire (data struct, scalar, enum) →
bool f(T *out, <inputs>, E *e)filling a caller-allocated*out.
emay beNULL, in which case the error value is dropped. Infallible producers return the value/pointer directly (no out-param). - pointer wire (opaque handle,
§Error handling (multiple error types)
Any type used as the E of a Result<T, E> return must be declared as an
error type via CbindgenBuilder::data_struct + CbindgenBuilder::error — otherwise the
build fails. Error types are ordinary data structs (marshalled by value) and
must additionally implement From<String>.
Built-in input converters that can fail (a String arg, an opaque handle
passed by value, a declared enum whose discriminant the caller chose) are
error-type-agnostic: they return Result<_, String>
where the Err is just a message. The generated wrapper for a Result<T, E>
function converts such a message into that function’s E via
<E as From<String>>::from(msg); the function’s own Err(E) is marshalled
directly through E’s output converter.
If a function can produce such an internal message but does not return
Result, that is a build error — suppress it by chaining CbindgenBuilder::panic
after the function declaration, which makes the wrapper panic! on the
internal error instead.
References to the original Rust types in generated bodies are written
fully-qualified against CbindgenBuilder::source_module so the generated file can
define its own identically-named #[repr(C)] wrapper structs without
colliding with the source crate’s types.
Structs§
- Cbindgen
- C / cbindgen language adapter. Build it with
CbindgenBuilder::new, declare the items to convert with the fluent methods, then drive it throughCbindgenBuilder::build→Cbindgen::write_rust. - Cbindgen
Builder
Functions§
- snake_
case - PascalCase → snake_case (
ZKeyExpr→z_key_expr). Convert aPascalCase/camelCaseidentifier tosnake_case(a convention-free helper, re-exported for consumers composing their ownCbindgenBuilder::mangle_rust_typerules). Thin alias for the core spelling, which sum-variant leaf naming shares.