Rust
Summary - FFI
Combine extern, repr(C) and CString to wrap a C call sending a string.
FFI summary
C functions are declared in an unsafe extern "C" block with C types (c_int, c_char, c_void). Shared structs must be #[repr(C)]. Strings are bridged with CString (Rust → C) and CStr (C → Rust). Callbacks are extern "C" fn, and panics can't cross the boundary. Resources are freed in Drop with the allocating side's function. For the reverse direction, #[unsafe(no_mangle)] pub extern "C" fn is used.
Offering a function to C
A library written in Rust can be called from C or other languages (Python, Swift). In Cargo.toml, crate-type = ["cdylib"] produces a shared library:
#[unsafe(no_mangle)]
pub extern "C" fn rs_topla(a: i32, b: i32) -> i32 {
a + b
}
// C side:
// int32_t rs_topla(int32_t a, int32_t b);
This function can also be called from Rust like a normal function, and assigned to a pointer of type extern "C" fn(i32, i32) -> i32. cbindgen generates the C header automatically.
Exercise Exported function
Write the rs_topla function above. Assign it to a function pointer with let f: extern "C" fn(i32, i32) -> i32 = rs_topla; and print the result of f(3, 4).
Show example solution
#[unsafe(no_mangle)]
pub extern "C" fn rs_topla(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let f: extern "C" fn(i32, i32) -> i32 = rs_topla;
println!("{}", f(3, 4));
}
Test yourself
-
What is <code>#[no_mangle]</code> for?
- It stops the compiler from changing the symbol name, so C finds the function by name
- It hides the function
- It inlines it
- It turns off debugging
Show answer
It stops the compiler from changing the symbol name, so C finds the function by name — Rust encodes symbol names with the module path (mangling); for exported functions this is turned off. In Rust 2024 it's written #[unsafe(no_mangle)].
-
Exported function
#[unsafe(no_mangle)]
pub ____ fn rs_topla(a: i32, b: i32) -> i32 {
a + b
}
Show answer
#[unsafe(no_mangle)]
pub extern "C" fn rs_topla(a: i32, b: i32) -> i32 {
a + b
}
-
Group summary
- extern "C" { }
- Call C
- #[repr(C)]
- C layout
- CString/CStr
- String bridge
- #[unsafe(no_mangle)]
- Offer to C
Next lesson: macro_rules!