Expand description
WeaveFFI: write safe Rust, get a stable C ABI and bindings for 11 languages.
This is the single crate a Rust producer depends on. Annotate an ordinary
module with module, tag the items you want to export, and call
export_runtime! once. The module expansion emits the
extern "C" thunks that the generated language bindings call, marshalling
every argument and result through the audited abi runtime so you never
write unsafe glue by hand. Every C symbol starts with the crate’s name
(calculator_math_add below).
#[weaveffi::module]
pub mod math {
/// The module's error domain; `Display` supplies the runtime message.
#[weaveffi::error]
#[derive(Debug)]
pub enum MathError {
/// Division by zero.
DivisionByZero = 1,
}
impl std::fmt::Display for MathError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("division by zero")
}
}
/// Add two integers.
#[weaveffi::export]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
/// Divide, reporting division by zero through the ABI's error channel.
#[weaveffi::export]
pub fn div(a: i32, b: i32) -> Result<i32, MathError> {
a.checked_div(b).ok_or(MathError::DivisionByZero)
}
}
// Export the runtime symbols (memory, errors, cancel tokens) once.
weaveffi::export_runtime!();The macro also embeds the API in the built library, which is what
weaveffi generate (run in the crate) reads to emit the header and
bindings, so the producer and the bindings can’t drift: the bindings
describe exactly what the library was compiled with.
§What you get
module- the driver attribute on an exportedmod.export- export a function (async fnis asynchronous; aResult-returning fn is fallible).record- a by-value struct serialized across the ABI.enumeration- a#[repr(i32)]C-style enum, or a rich enum with data-carrying variants.interface- an opaque, reference-counted object type; pass one as&TorArc<T>, return one asSelf,T, orArc<T>.error- the module’s error domain.callback_interface- a trait the consumer implements; accept one asArc<dyn Trait>(orOption<Arc<dyn Trait>>). Its methods returnResult<T, ForeignError>;throwslets one report the module’s domain errors.cancellable- mark anasync fnas accepting a cancel token.set_spawner- install the executor async exports run on; the default is a small pool of worker threads, or Tokio with thetokiofeature.export_runtime!- export the runtime symbols (memory, errors, cancel tokens, ABI version) under the crate’s prefix, once per library.abi- the C ABI runtime: the error struct, memory helpers, and the marshalling converters the expansion calls.
§Features
leak-checkcounts live objects, callbacks, iterators, cancel tokens, and returned allocations, reported by{prefix}_debug_liveso a test harness can assert a consumer released everything. Off by default.tokioruns exportedasync fns on Tokio: the current runtime when a launcher is called from inside one, otherwise a multi-thread runtime created on first use.set_spawnerstill overrides it. Off by default.
Re-exports§
pub use abi::Iter;pub use abi::CancelToken;pub use abi::ForeignError;pub use abi::ErrorDomain;pub use abi::ErrorReport;pub use abi::set_spawner;pub use abi::Spawner;pub use abi::BoxFuture;
Modules§
- abi
- The stable C ABI runtime: the error struct, memory helpers, reference-counted objects, cancel tokens, callback-interface vtables, iterators, the value-buffer codec, and the async executor hook.
Macros§
- export_
runtime - Emit the runtime symbols every WeaveFFI library exports, prefixed with the
crate’s name:
{prefix}_abi_version,{prefix}_error_set,{prefix}_error_set_payload,{prefix}_error_clear,{prefix}_error_free,{prefix}_alloc,{prefix}_free_bytes, the four{prefix}_cancel_token_*functions, and{prefix}_debug_live.
Attribute Macros§
- callback_
interface - Declare a callback interface: a trait whose
&selfmethods the consumer implements. Producers accept one asArc<dyn Trait>(orOption<Arc<dyn Trait>>). Every method returnsResult<T, weaveffi::ForeignError>, which carries the consumer’s failure as a value. - cancellable
- Mark an
async fnas cancellable: it takes aweaveffi::CancelTokenas its final parameter, and cancelling the token completes the call with the cancelled code. - enumeration
- Declare an enum exported by value: a
#[repr(i32)]C-style enum, or a rich enum whose variants carry named fields. - error
- Declare the module’s error domain from an enum with explicit
discriminants (the stable error codes). The enum must implement
std::fmt::Display, which supplies the runtime message; each variant’s doc comment is the documented default message. - export
- Export a function across the FFI boundary. An
async fnlowers to an asynchronous symbol; afn -> Result<T, E>is fallible. - interface
- Declare an interface: an opaque, reference-counted object type with
constructors, methods, and statics read from its
implblock. Methods take&selforself: Arc<Self>; the type must beSend + Sync. - module
- Mark an inline
modas an exported WeaveFFI namespace. - record
- Declare a by-value record (struct) serialized in the value-buffer format when it crosses the ABI.
- throws
- Mark a callback-interface method as able to report the error domain
in scope: the consumer may fail with one of its codes, which the
producer decodes with
weaveffi::ForeignError::domain.