Rust: Expose Functions to C with `#[no_mangle]`
The #[no_mangle] attribute tells the Rust compiler not to alter a function's name, exposing a stable symbol for C code to call. Use it with extern "C" to create Rust libraries for other languages. The footgun is forgetting extern "C", causing crashes.
Why it exists
By default, the Rust compiler "mangles" function names to encode information like module paths, ensuring uniqueness within a Rust project. A function named process might become _ZN4my_crate7process17hdeadbeef.... This mangled name is unusable by external C code, which expects a simple, stable name like process. We need a way to tell Rust to produce a C-compatible function symbol.
The mental model
Think of #[no_mangle] as putting a permanent, public name tag on a Rust function. Without it, Rust gives the function a complex, internal-only ID. With it, anyone outside (like a C linker) can find the function by its simple, declared name. It's the difference between a private employee ID and a public "Hello, My Name Is..." sticker.
How it works
The #[no_mangle] attribute instructs the compiler to inhibit name mangling for the item it's attached to. This exports the function with the exact name from your source code. For it to be callable from C, you must also use extern "C". This second piece tells the compiler to use the C Application Binary Interface (ABI), which defines how arguments are passed and who cleans up the stack. Using both ensures the name is findable and the call mechanics are compatible.
When to use it
Use #[no_mangle] and extern "C" when writing a Rust library that needs to be called from a non-Rust language. This is the foundation for creating dynamic libraries (.so, .dll, .dylib) or static libraries (.a) in Rust for consumption by C, C++, Python (via ctypes), Ruby, Node.js, and others.
When not to use it
Do not use it for functions that are only called from other Rust code. Rust's default name mangling and ABI are more optimized and support features like generics and trait methods, which a C ABI does not. Using it on internal-only functions discards potential compiler optimizations and safety features.
One canonical example
To create a Rust function add that can be called from C, you would write:
#[no_mangle]
pub extern "C" fn add(left: i32, right: i32) -> i32 {
left + right
}
A C program could then declare int32_t add(int32_t, int32_t); and call it after linking against the compiled Rust library. Note the use of pub, extern "C", and C-compatible types like i32.
Interview question
To expose a Rust function to C, ensuring both a stable, findable name and C-compatible calling conventions, which attributes are required?
- a.pub and extern "C"
- b.#[no_mangle] and extern "C"Correct
- c.pub and #[no_mangle]
- d.#[export_name] and extern "C"
Why? this is the answer
The #[no_mangle] attribute prevents Rust from altering the function's name, making it findable by C. The extern "C" declaration ensures the function uses the C Application Binary Interface (ABI), which is crucial for C code to call it correctly. Option A is incomplete as it lacks #[no_mangle], meaning the name would still be mangled and unfindable.
Just read this? Test yourself on what you have been reading.
Read the original → doc.rust-lang.org
- #rust
- #ffi
- #c
- #interop
- #no_mangle
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on rust — each one lists the topics its interview covers.
See open roles