Rust's `bindgen`: Auto-Generate FFI to C/C++
`bindgen` is a translator that reads C/C++ headers and writes the unsafe Rust FFI code to call them. It's used to integrate Rust with existing C libraries, like system APIs or legacy code, saving you from writing bindings by hand.
WHY IT EXISTS Rust needs a way to interoperate with the vast ecosystem of existing C and C++ libraries. Manually writing Foreign Function Interface (FFI) bindings is tedious, repetitive, and highly error-prone, as you must perfectly match C types, struct layouts, and function signatures in Rust. bindgen was created to automate this entire process.
THE MENTAL MODEL Think of bindgen as a specialized compiler that takes C/C++ header files (.h) as input and outputs a Rust source file (.rs). This generated file contains the extern "C" blocks and #[repr(C)] structs needed to call the C code from Rust. It's a bridge-builder, automatically constructing the unsafe foundation for interoperability.
HOW IT WORKS bindgen uses libclang to parse C/C++ headers. It analyzes the Abstract Syntax Tree (AST) to understand the types, structs, unions, and functions declared. From this, it generates equivalent Rust definitions. For example, a C struct CoolStruct becomes a Rust #[repr(C)] pub struct CoolStruct, and a C function cool_function becomes a declaration inside an extern "C" block. It typically runs as part of your crate's build process via a build.rs script.
WHEN TO USE IT Use bindgen whenever you need to call into a C or C++ library from Rust. This is common for interacting with operating system APIs, using established libraries for tasks like graphics or physics, or gradually migrating a legacy C/C++ codebase to Rust by wrapping parts of it.
WHEN NOT TO USE IT Don't use bindgen if a high-quality, community-maintained "-sys" crate already exists for the library you need. For example, instead of running bindgen on libgit2 yourself, use the libgit2-sys crate. Also, bindgen only creates the raw bindings; it doesn't create a high-level, safe, and idiomatic Rust wrapper. That is a separate, manual step.
ONE CANONICAL EXAMPLE Given a C header file wrapper.h containing typedef struct CoolStruct { int x; } CoolStruct; void cool_function(CoolStruct* cs);, bindgen generates the corresponding Rust code. This includes a #[repr(C)] struct CoolStruct with a field x of type c_int, and an extern "C" block declaring pub fn cool_function(cs: *mut CoolStruct). This allows your Rust code to create a CoolStruct, get a raw pointer to it, and pass it to the C function.
Read the original → rust-lang.github.io
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.