Unsafe External Functions

Functions in a foreign language may also be unsafe:

use std::ffi::c_char;

unsafe extern "C" {
    // `abs` doesn't deal with pointers and doesn't have any safety requirements.
    safe fn abs(input: i32) -> i32;

    /// # Safety
    ///
    /// `s` must be a pointer to a NUL-terminated C string which is valid and
    /// not modified for the duration of this function call.
    unsafe fn strlen(s: *const c_char) -> usize;
}

fn main() {
    println!("Absolute value of -3 according to C: {}", abs(-3));

    unsafe {
        // SAFETY: We pass a pointer to a C string literal which is valid for
        // the duration of the program.
        println!("String length: {}", strlen(c"String".as_ptr()));
    }
}
  • Rust used to consider all extern functions unsafe, but this changed in Rust 1.82 with unsafe extern blocks.
  • abs must be explicitly marked as safe because it is an external function (FFI). Calling external functions is usually only a problem when those functions do things with pointers which which might violate Rust’s memory model, but in general any C function might have undefined behaviour under any arbitrary circumstances.
  • The "C" in this example is the ABI; other ABIs are available too.
  • Note that there is no verification that the Rust function signature matches that of the function definition – that’s up to you!