On this page
C ABI and bindgen
The first step in calling C from Rust is to ensure consistent type layout—
repr(C)forces Rust structs to lay out fields according to the C ABI, aligning byte-for-byte with structs in C headers. bindgen automatically generates corresponding Rust types and function signatures from C headers, automating the tedious and error-prone manual maintenance of Rust/C type mappings. The core of safe callbacks is: panics must not unwind across FFI boundaries when C calls back into Rust.
C ↔ Rust Type Mapping
FFI type correspondence is not automatic—you must explicitly use C-compatible types from std::os::raw or the libc crate:
| C type | Rust type (libc) | Notes |
|---|---|---|
int | c_int (i32) | |
long | c_long | 32-bit on Windows, 64-bit on Linux! |
size_t | usize | |
char * (string) | *const c_char → CStr::from_ptr() | |
void * | *mut c_void | |
| struct pointer (opaque) | *mut MyStruct | Do not dereference; only pass around |
| enum | #[repr(C)] enum | C enums are c_int sized |
Key pitfall: The size of long is 4 bytes on LLP64 (Windows) and 8 bytes on LP64 (Linux). If your C code relies on long being 8 bytes, use i64 instead on Windows.
bindgen Automation
bindgen automatically generates Rust extern function declarations, structs, and constants from C headers:
// build.rs
// src/lib.rs
include!;
bindgen handles: basic type mapping, struct alignment, nested structs, function pointers, conditional defines. It cannot handle: inline functions (must be manually ported to Rust), C++ templates.
Callbacks: Safe Boundaries for C Calling Rust
extern "C"
unsafe
Panics in callbacks must not cross FFI boundaries—doing so results in undefined behavior. Setting panic = "abort" in Cargo.toml is the most straightforward way to eliminate this risk. If you must retain unwinding, wrap all logic inside the callback with catch_unwind.
References
- bindgen: rust-lang.github.io/rust-bindgen
- Rustonomicon: FFI
- libc crate: docs.rs/libc
Keywords: C ABI, bindgen, c_int, c_long, c_void, callback, panic across FFI, #[repr(C)]