Interop Basics
10 examples for choosing how Rust talks to Python, Node.js, C/C++, and other runtimes.
Prerequisites
- Rust 1.97.0 (edition 2024)
- Clear ownership of which language owns the process and the GC heap
Basic Examples
1. Decision Matrix
| Goal | Primary tool |
|---|---|
| Python extension module | PyO3 + maturin |
| Node native addon | napi-rs |
| C/C++ static or dynamic lib | extern "C" + cbindgen |
| Browser compute | wasm-bindgen |
| Sandboxed plugin | WASM component / WASI |
Pick one primary boundary per integration point.
2. Who Owns main?
Rust owns main -> embed Python/JS via FFI (PyO3, Neon)
Host owns main -> export Rust as library (cdylib/staticlib)The owner controls initialization, signal handling, and allocator choice.
3. Stable ABI Requirement
#[repr(C)]
pub struct Point {
pub x: f64,
pub y: f64,
}- C/C++ interop needs
repr(C)andextern "C" - Rust-to-Rust across crates does not need C ABI
- Never expose
StringorVecin C headers
Related: Exposing a Rust Library to C/C++
4. Error Mapping Pattern
#[repr(C)]
pub enum Status {
Ok = 0,
InvalidInput = 1,
Oom = 2,
}Map Rust Result to integer codes or out-parameters at the boundary.
5. Memory Ownership Contract
Rust allocates -> Rust frees (export mylib_free)
C allocates -> C frees
Copy at boundary -> safest default for small dataDocument who frees every pointer in the header.
Related: Data Marshalling
6. PyO3 Quick Peek
use pyo3::prelude::*;
#[pyfunction]
fn add(a: i64, b: i64) -> PyResult<i64> {
Ok(a + b)
}Python calls Rust for hot paths. Rust calls Python for orchestration when needed.
Related: PyO3
7. napi-rs Quick Peek
#[napi]
pub fn fib(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fib(n - 1) + fib(n - 2),
}
}Generates TypeScript types for Node consumers automatically.
Related: Node.js with napi-rs
8. When WASM Beats Native FFI
- Cross-platform plugins without per-OS builds
- Sandboxed untrusted code
- Same module in browser and edge runtime
Related: Embedding Rust in Other Runtimes
Intermediate Examples
9. maturin for Python Packaging
maturin develop
python -c "import myrust; print(myrust.add(1, 2))"Builds wheels with Rust inside for pip install.
Related: maturin
10. Integration Checklist
- Ownership rules written in README and header
- Panics caught at FFI boundary
- CI builds all target triples you ship
- Integration tests in the host language
- Semver policy for the public boundary API
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.