proffi is a protobuf-defined FFI framework built on top of UniFFI. Instead of
hand-writing per-language type-mapping glue, you declare your library's
interface as a .proto service, write Rust handlers, and proffi collapses
the entire cross-language boundary to a single Vec<u8> -> Vec<u8> ABI. The
generated SDK for each target language wraps that boundary with typed stubs
derived from the same .proto. JavaScript support is achieved via plain-C
loaders (koffi), which UniFFI's native bindings do not cover.
Status: pre-alpha. Design notes: docs/2026-04-29-design.md.
The crates are not yet published to crates.io. Everything below works from inside this repo.
nix develop # one-time: drops you into a shell with every tool
just smoke # runs all three language smokes (Python, Kotlin, JS)If you use direnv, direnv allow once after cloning
and the shell auto-loads on every cd into the repo.
Individual smokes:
just smoke-python
just smoke-kotlin
just smoke-javascriptInstall the prerequisites listed below, then:
just smokeOr run a single smoke directly:
bash examples/greeter/smoke/python/run.sh
bash examples/greeter/smoke/kotlin/run.sh
bash examples/greeter/smoke/javascript/run.shjust test # Rust test suite (cargo test --workspace)
just ci # test + all three smokes
just clean # wipe cargo artefacts and per-smoke build dirs
just --list # show all available recipes| Tool | Minimum version | Notes |
|---|---|---|
| Rust (stable) | 1.76+ | rustup recommended |
protoc |
3.x | Protocol Buffers compiler |
just |
any recent | Recipe runner — brew install just / cargo install just |
| Python 3 | 3.8+ | For the Python smoke |
| Node.js + npm | 18 LTS or later | For the JavaScript smoke |
| JDK | 17+ | For the Kotlin smoke |
nix develop provides all of the above automatically.
examples/greeter/ is the reference implementation.
- Proto definition:
examples/greeter/proto/greeter.proto - Rust handlers:
examples/greeter/src/lib.rs - Smoke tests:
examples/greeter/smoke/{python,kotlin,javascript}/
-
Declare a
servicein a.protofile withrpcmethods. -
Write Rust handlers annotated with
#[proffi::rpc(service = "...", method = "...")]. -
Call
proffi::setup!()in your crate root;proffi-buildhandles protobuf codegen and FFI wiring inbuild.rs. -
Compile your crate as a
cdylib, then run theproffiCLI to emit a typed SDK for the target language:proffi --crate-name <crate> generate \ --lang <python|kotlin|javascript> \ --out <output-dir> \ --lib-path <path/to/libcrate.dylib>
See
examples/greeter/smoke/<lang>/run.shfor a full worked invocation. -
The shared library is loaded directly by the generated SDK using the host language's FFI mechanism (ctypes for Python, JNA for Kotlin, koffi for JavaScript).
Apache-2.0. See LICENSE.