rust_c_api
Showcase: implement library logic once in Rust, expose a stable C ABI, then bind it from C, Go, Python, Ruby, another Rust crate, Node (koffi), or the browser (WASM)—without rewriting the algorithms.
Why this repo exists
Production SDKs often need the same behavior in many runtimes. Rust is a strong implementation language; a C-compatible FFI layer is the lingua franca most languages can call. This project walks through that stack in small steps: pure core, thin ffi, generated header, and parallel wrappers that all agree on wrappers/fixtures/expected.json.
Repository identity
This standalone study project lives at github.com/jacksmithinsulander/rust-c-api-study. Canonical names:
| What | Name |
|---|
| GitHub repo | rust-c-api-study |
| Rust crate / cdylib | rust_c_api |
| Go module | github.com/jacksmithinsulander/rust-c-api-study/wrappers/go |
Python package (pyproject.toml) | rust-c-api-study-ffi |
Node package (package.json) | rust-c-api-ffi |
Wrappers load target/debug/librust_c_api locally only — no dependency on other GitHub orgs or private remotes.
System layers
flowchart TB
subgraph consumers [Language consumers]
CNative[C tests]
Go[Go cgo]
Py[Python ctypes]
Ruby[Ruby ffi]
Node[TypeScript koffi]
RustFfi[Rust extern C]
Browser[Browser wasm-bindgen]
end
subgraph boundary [Stable C ABI]
Header[include/rust_c_api.h]
Exports["ffi/mod.rs no_mangle exports"]
Types["ffi/types.rs repr C structs"]
end
subgraph logic [Pure Rust]
Core[src/core business logic]
end
consumers --> Header
Header --> Exports
Exports --> Core
Types --> Exports
API taxonomy
flowchart LR
subgraph atomic [Atomic exports]
F5[fibonacci_first_five_values]
Lookup[fibonacci_lookup]
Div[safe_divide_i64]
end
subgraph composite [Composite exports]
Fold[fold_fibonacci_values]
FibDiv[divide_fibonacci_numbers_at_indices]
Fetch[fetch_jsonplaceholder_user]
end
Fold --> F5
FibDiv --> Lookup
FibDiv --> Div
Fetch --> Http[core/http_fetch]
| Function | Layer | Description |
|---|
fibonacci_first_five_values | Atomic | First five Fibonacci numbers |
fibonacci_lookup | Atomic | Fibonacci at index (max 93) |
safe_divide_i64 | Atomic | Integer divide with remainder |
fold_fibonacci_values | Composite | Fold first-five sequence via C callback |
divide_fibonacci_numbers_at_indices | Composite | Lookup two Fibonacci values, then divide |
fetch_jsonplaceholder_user | Composite | HTTP fetch user 1 (native sync only) |
Details and status codes: src/README.md. Header: include/rust_c_api.h (generated on cargo build).
On error paths, only status is guaranteed; other fields may be zeroed.
Reading guide (tutorial order)
- This page — architecture and links below.
- src/README.md — read
core/fibonacci.rs → ffi/types.rs → ffi/mod.rs.
- include/README.md — generated header contract.
- c/README.md — minimal native consumer.
- wrappers/README.md — pick one binding style.
- Optional: wrappers/wasm/README.md — WASM + browser demo.
Documentation map
Layout
src/core/ pure Rust logic (unit-tested)
src/ffi/ #[repr(C)] types and #[no_mangle] exports
include/ rust_c_api.h (cbindgen)
c/tests/ native C integration tests
wrappers/ Python, TypeScript, Go, Ruby, Rust, WASM
wrappers/wasm/web/ browser demo (Vite + WASM)
wrappers/fixtures/ shared expected.json
Build and verify
flowchart LR
build[cargo build]
header[cbindgen to include/]
libcargo[cdylib librust_c_api]
testC[c/Makefile test]
testWrap[wrappers tests vs expected.json]
build --> header
build --> libcargo
libcargo --> testC
libcargo --> testWrap
make test-all
Runs cargo build, C tests, and all wrapper tests against expected.json.
Prerequisites
- Rust (rustup recommended)
- Node.js 20+ for TypeScript wrapper and web demo
- Network for
fetch_jsonplaceholder_user tests
WASM / browser
make build-wasm # wrappers/wasm/pkg/
make dev-web # Vite dev server
See wrappers/wasm/README.md for toolchain notes (wasm32-unknown-unknown, wasm-pack).
Navigation