Introduction
WeaveFFI generates idiomatic bindings for 11 languages from one API
definition, over a stable C ABI. Write the API as safe Rust annotated with
#[weaveffi::module], or as a YAML, JSON, or TOML IDL implemented by any
library that can export C symbols (C, C++, Zig, and so on). WeaveFFI emits
packages for C, C++, Swift, Kotlin, Node.js, WebAssembly, Python, .NET, Dart,
Go, and Ruby that all call the same C functions.
The design in one page
One definition, two front doors. A Rust producer annotates ordinary
modules; the #[weaveffi::module] macro emits the extern "C" thunks and
embeds a description of the API in the compiled library, and the CLI reads
that description back out to emit the bindings, so the bindings you ship
describe exactly the library you compiled, #[cfg] included. A non-Rust
producer writes an IDL instead and implements the C
header WeaveFFI generates from it.
Identity drives every name. A library has one resolved
identity: a package name, a C symbol prefix, and a
native library base name. For a Rust producer all three come from the crate
(kvstore gives kvstore_kv_Store_open, libkvstore.so, and an npm, PyPI,
or NuGet package named kvstore). Nothing a generator emits is named after
WeaveFFI, so any number of WeaveFFI-built libraries can live in one process.
A small, explicit C ABI. Revision 4 has five value
families: direct scalars, UTF-8 strings and bytes as (ptr, len) runs,
serialized value buffers for records, enums,
optionals, lists, and maps, reference-counted objects, and
consumer-implemented callback vtables. Every fallible call reports through a
{prefix}_error struct. Async functions complete through a callback that
fires exactly once, and cancellation is a first-class runtime code. Every
consumer checks the ABI revision and each module’s contract table (a hash of
every declaration’s signature) when it loads the library, so a stale binding
fails loudly, naming the declaration that changed, instead of misreading
memory.
Idiomatic generators. Each target maps the model onto its own idioms:
objects become classes with deterministic disposal and a garbage-collector
backstop, async functions become async/await, coroutines, promises, or
tasks with native cancellation, iterators stay lazy, and error domains
become typed exceptions or error values. The
capability matrix summarizes all eleven.
Standalone output. Generated packages are self-contained: helper code
(the value-buffer codec, error types, object wrappers, loaders) is generated
into each package, so consumers never install WeaveFFI. weaveffi package
bundles prebuilt native libraries into publishable packages per ecosystem.
Where to next
- Getting Started: a Rust producer called from Python and C in a few minutes, plus the IDL path for a C implementation.
- The Rust Producer Macro: every supported signature and what the macro rejects.
- C ABI Contract: the normative description of the boundary.
- Comparison and FAQ: how WeaveFFI relates to UniFFI, Diplomat, cbindgen, and the single-language bridges.
- Stability and Versioning: what the version numbers promise, and how to migrate to schema 0.11 and ABI revision 4.