Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Comparison

WeaveFFI sits in a crowded ecosystem of FFI tooling. This page is an honest, side-by-side look at how it compares to the projects you are most likely to evaluate against it: UniFFI, cbindgen, diplomat, SWIG, and autocxx.

All comparisons reflect the public state of each project at the time of writing. If something here is out of date, please open a PR.

At a glance

WeaveFFIUniFFIcbindgendiplomatSWIGautocxx
Source languageRust / C / C++ / Zig (anything with a C ABI)RustRustRustC / C++C++
Input formatYAML / JSON / TOML IDLUDL or proc-macro on RustRust source (annotated)Rust source (annotated)C/C++ headers + .i interfaceC++ headers
Languages
C
C++✓ (RAII, std::optional/vector/unordered_map)✓ (header)✓ (its purpose)
Swift✓ (SwiftPM, async/await, throws)
Kotlin / Android (JNI)✓ (Kotlin + JNI shim + Gradle)✓ (Java via JNI)
Node.js✓ (N-API + .d.ts)community add-on✓ (JavaScriptCore/V8)
WebAssembly✓ (loader + .d.ts)✓ (JS via WASM)
Python✓ (ctypes + .pyi)
.NET / C#✓ (P/Invoke + .csproj)✓ (community)
Dart / Flutter✓ (dart:ffi)community
Go✓ (CGo)community
Ruby✓ (FFI gem)
Type system
Primitives + string
bytes / byte slices✓ (raw)partial
Structs✓ (opaque + getters)✓ (records & objects)✓ (#[repr(C)])✓ (opaque)
Enums w/ explicit discriminants
Optionals✓ (T?)partialpartial
Lists✓ ([T])partial
Maps✓ ({K:V})partialpartial
Typed handles (handle<T>)✓ (objects)✓ (opaque)partial
Borrowed types (&str, &[u8])partial
Iterators (iter<T>)✓ (callbacks)partialpartial
Async functions✓ (callback ABI + async/await/Promise/suspend/Task<T>)partial
Cancellable futures✓ (weaveffi_cancel_token)partial
Callbacks / event listeners✓ (module-level)✗ (raw fn ptrs)partialpartialpartial
Cross-module type referencesn/a
Nested modulespartialn/a
Workflow
Single-binary CLI install✓ (cargo install weaveffi-cli)system package
Standalone publishable packages✓ (npm, SwiftPM, pub.dev, NuGet, gem, etc.)partialn/apartialpartialn/a
JSON Schema for IDL editor supportn/an/an/a
extract from annotated source✓ (Rust)✓ (proc-macro)✓ (Rust)✓ (Rust)n/a✓ (C++)
watch mode✓ (--watch)partial
format IDL canonicalizern/an/an/a
Custom template overridespartial (Mako)partial✓ (%typemap)partial
Snapshot-tested generator outputpartial
Maturitypre-1.01.0+ in Mozilla shipping products1.0+ widely deployedpre-1.030+ years, ubiquitouspre-1.0
LicenseMIT OR Apache-2.0MPL-2.0MPL-2.0BSD-3-ClauseGPL with FOSS exceptionMIT OR Apache-2.0

Legend: ✓ = first-class support; partial = supported with caveats or via extensions; ✗ = not supported; n/a = not applicable to that tool’s scope.

Where competitors are stronger

We try hard to be honest about the trade-offs. Pick the right tool for the job:

  • UniFFI is more mature. It ships in production at Mozilla (Firefox Sync, Glean, Nimbus) and has years of battle-testing across iOS, Android, and desktop. If you only need Swift, Kotlin, and Python today and you are comfortable with a UDL-or-proc-macro workflow, UniFFI is the safer choice.
  • cbindgen is simpler if all you want is a C header. WeaveFFI generates a C header and ten other targets. If you only consume the C surface from C/C++ code, cbindgen has less ceremony, no IDL file, and a smaller dependency footprint.
  • diplomat has a more polished C++ story. Its C++ output uses richer templates and integrates more cleanly with existing C++ codebases. WeaveFFI’s C++ output is RAII-based and includes a CMakeLists.txt, but it’s optimized for greenfield projects, not for slotting into a 20-year-old C++ build system.
  • SWIG covers languages WeaveFFI doesn’t. Lua, Tcl, R, Octave, Perl, PHP: if your target is exotic, SWIG probably has a generator. SWIG also natively understands C and C++ headers, so you don’t need to author an IDL at all.
  • autocxx is unmatched for “wrap an existing C++ library.” It reads your C++ headers directly and uses bindgen + cxx under the hood. WeaveFFI does not parse C++; you describe the surface area you want to expose, and WeaveFFI generates the contract.
  • No IDE plugin yet. The other tools listed have community VSCode/JetBrains extensions of varying quality. WeaveFFI ships a JSON Schema for editor autocompletion and a format command, but no first-party IDE plugin.
  • No formal stability guarantee yet. WeaveFFI is pre-1.0; the IDL, generated output, and runtime symbol names can shift in minor releases. UniFFI, cbindgen, and SWIG offer stronger compatibility commitments today.

When to choose WeaveFFI

WeaveFFI is the right pick when you want:

  1. One source of truth for many languages. If your library has to land in npm and SwiftPM and PyPI and NuGet and pub.dev and RubyGems and a Go module and a Gradle artifact, that’s the WeaveFFI sweet spot. UniFFI covers a smaller subset out of the box; cbindgen and autocxx don’t try.
  2. Standalone, publishable consumer packages. Generated packages are self-contained: a Swift consumer adds your .xcframework + a SwiftPM manifest and is done. No “install WeaveFFI” step on the consumer side.
  3. A native library that isn’t (only) Rust. WeaveFFI works against anything that exposes a stable C ABI: Rust (with --scaffold convenience), C, C++, Zig, etc. UniFFI and diplomat assume Rust; autocxx assumes C++.
  4. Idiomatic per-target output, not a lowest-common-denominator API. Async functions become async/await in Swift, Promises in Node, suspend fun in Kotlin, async def in Python, and Task<T> in C#, all from the same async: true flag in the IDL.
  5. A CLI workflow with validate, lint, diff, watch, and format. WeaveFFI is built for monorepos and CI: every sub-command has a --format json output mode, and diff --check and format --check are designed to drop into pre-commit and CI gates.
  6. Honest pre-1.0 churn, documented every release. Every breaking IDL change is called out in CHANGELOG.md with a migration note, and weaveffi validate rejects out-of-date schema versions with an actionable error instead of silently misreading them.

When to choose something else

  • You only need Swift + Kotlin + Python and want maximum stability: use UniFFI.
  • You only need a C header for a Rust crate: use cbindgen.
  • You’re wrapping a large existing C++ codebase: use autocxx (or cxx + bindgen directly).
  • Your target language is Lua, Tcl, R, Octave, Perl, or PHP: use SWIG.
  • You need a battle-tested C++ binding generator with rich template support: use diplomat or SWIG.

Migrating to / from WeaveFFI

WeaveFFI’s IDL is intentionally close to UniFFI’s UDL surface area, which makes hand-porting straightforward in either direction. There is no automatic UDL → WeaveFFI converter today, but weaveffi extract can read annotated Rust source and produce a starting IDL, which is often the fastest path off any Rust-only generator. See the extract guide for details.