Skip to content

boltffi/boltffi

Repository files navigation

BoltFFI

A high-performance multi-language bindings generator for Rust. Up to 1,000x faster than UniFFI. Up to 450x faster than wasm-bindgen.

Quick links: User Guide | Tutorial | Getting Started

Performance

vs UniFFI (Swift/Kotlin)

Benchmark BoltFFI UniFFI Speedup
noop <1 ns 1,416 ns >1000x
echo_i32 <1 ns 1,416 ns >1000x
counter_increment (1k calls) 1,083 ns 1,388,895 ns 1,282x
generate_locations (1k structs) 4,167 ns 1,276,333 ns 306x
generate_locations (10k structs) 62,542 ns 12,817,000 ns 205x

vs wasm-bindgen (WASM)

Benchmark BoltFFI wasm-bindgen Speedup
1k particles 29,886 ns 13,532,530 ns 453x
100 particles 3,117 ns 748,287 ns 240x
1k locations 21,931 ns 4,037,879 ns 184x
1k trades 42,015 ns 5,781,767 ns 138x
100 locations 2,199 ns 283,753 ns 129x

Full benchmark code: benchmarks

Why BoltFFI?

Serialization-based FFI is slow. UniFFI serializes every value to a byte buffer. wasm-bindgen materializes every struct as a JavaScript object. That overhead shows up even when you're making tens or hundreds of FFI calls per second.

BoltFFI uses zero-copy where possible. Primitives pass as raw values. Structs with primitive fields pass as pointers to memory both sides can read directly. WASM uses a wire buffer format that avoids per-field allocation. Only strings and collections go through encoding.

What it does

Mark your Rust types with #[data] and functions with #[export]:

use boltffi::*;

#[data]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

#[export]
pub fn distance(a: Point, b: Point) -> f64 {
    let dx = b.x - a.x;
    let dy = b.y - a.y;
    (dx * dx + dy * dy).sqrt()
}

Run boltffi pack:

boltffi pack apple
# Produces: ./dist/apple/YourCrate.xcframework + Package.swift

boltffi pack android
# Produces: ./dist/android/jniLibs/<abi>/libyour_crate.so + Kotlin bindings

boltffi pack wasm
# Produces: ./dist/wasm/pkg/*.wasm + TypeScript bindings + npm package

Android ABI selection is configurable in boltffi.toml:

[targets.android]
architectures = ["arm64"]

Apple slice selection is configurable too:

[targets.apple]
ios_architectures = ["arm64"]
simulator_architectures = ["arm64"]
include_macos = true
macos_architectures = ["arm64"]

Any Apple architecture list can be set to [] to exclude that slice family. For example, set ios_architectures = [] when you want simulator-only Apple packaging from a config overlay. BoltFFI still requires at least one Apple slice overall.

When architectures is omitted, BoltFFI keeps the existing default Android matrix: arm64, armv7, x86_64, and x86. boltffi pack android --no-build now validates that each configured ABI already has a built Rust static library and ignores stale artifacts for unconfigured ABIs.

You can also apply per-invocation overlays without mutating the tracked base config. BoltFFI still requires a base boltffi.toml, then merges the overlay on top for that one command:

boltffi --overlay boltffi.ci.toml pack android
boltffi --overlay boltffi.release.toml pack all --release

This is useful for CI, release builds, or machine-local overrides. boltffi init does not accept --overlay.

Use it from Swift, Kotlin, or TypeScript:

let d = distance(a: Point(x: 0, y: 0), b: Point(x: 3, y: 4)) // 5.0
val d = distance(a = Point(x = 0.0, y = 0.0), b = Point(x = 3.0, y = 4.0)) // 5.0
import { distance } from 'your-crate';
const d = distance({ x: 0, y: 0 }, { x: 3, y: 4 }); // 5.0

The generated bindings use each language's idioms. Swift gets async/await. Kotlin gets coroutines. TypeScript gets Promises. Errors become native exceptions.

Supported languages

Language Status
Swift Full support
Kotlin Full support
Java Full support
WASM/TypeScript Full support
C Partial
Python In progress
C++ Planned
C# Planned
Ruby Planned
Dart Planned
Scala Planned
Go Planned
Lua Potential
R Potential

Want another language? Open an issue.

Installation

cargo install boltffi_cli

Add to your Cargo.toml:

[dependencies]
boltffi = "0.1"

[lib]
crate-type = ["cdylib", "staticlib"]

Documentation

Alternative tools

Other tools that solve similar problems:

  • UniFFI - Mozilla's binding generator, uses serialization-based approach
  • Diplomat - Focused on C/C++ interop
  • cxx - Safe C++/Rust interop

Contributing

Contributions are warmly welcomed 🙌

License

BOLTFFI is released under the MIT license. See LICENSE for more information.

About

A high-performance multi-language bindings generator for Rust, up to 1,000x faster than UniFFI. Ship Rust libraries that feels native to Swift, Kotlin, and more

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors