Rust FFI (Foreign Function Interface)
Learn Rust through interactive, bite-sized lessons. Master memory safety without garbage collection.
Start Rust Journey →Rust's Foreign Function Interface (FFI) is a powerful feature that allows Rust code to interact with code written in other languages, primarily C. This capability is crucial for integrating Rust with existing codebases and leveraging libraries written in other languages.
Understanding FFI in Rust
FFI enables Rust programs to call functions in C libraries and expose Rust functions to C code. This interoperability is essential for system programming and when working with legacy systems.
Key Concepts
- External functions
- Unsafe blocks
- Type mapping between Rust and C
- Linking with external libraries
Calling C Functions from Rust
To call a C function from Rust, you need to declare the function using the extern keyword and wrap the call in an unsafe block.
use std::os::raw::c_int;
extern "C" {
fn abs(input: c_int) -> c_int;
}
fn main() {
unsafe {
let result = abs(-42);
println!("Absolute value of -42: {}", result);
}
}
In this example, we're calling the C abs() function from the standard C library. The extern "C" block declares the function signature, and the unsafe block is required because Rust can't guarantee the safety of external function calls.
Exposing Rust Functions to C
Rust functions can be exposed to C by using the #[no_mangle] attribute and the extern "C" modifier.
#[no_mangle]
pub extern "C" fn rust_function(x: i32) -> i32 {
x * 2
}
This Rust function can now be called from C code. The #[no_mangle] attribute prevents name mangling, ensuring the function name remains unchanged in the compiled binary.
Type Mapping
When working with FFI, it's crucial to understand how Rust types map to C types. Rust provides primitive types that correspond to C types in the std::os::raw module.
| Rust Type | C Type |
|---|---|
c_char |
char |
c_int |
int |
c_long |
long |
c_void |
void |
Best Practices and Considerations
- Always use
unsafeblocks when calling C functions - Be cautious with memory management when working with C code
- Use the Rust Unsafe Code features judiciously
- Consider using higher-level abstractions like the
libccrate for common C functions - Test FFI code thoroughly to ensure correct behavior and memory safety
Conclusion
Rust's FFI capabilities provide a bridge between Rust and other languages, particularly C. This feature is invaluable for systems programming and integrating Rust with existing codebases. While powerful, FFI requires careful handling to maintain Rust's safety guarantees.
For more advanced topics related to FFI, consider exploring Rust Advanced Traits and Rust Advanced Types. These concepts can help you create more sophisticated FFI interfaces.