CodeBlanks Logo Icon CodeBlanks

FFI call

Call foreign functions with extern "C".

An FFI call

The foreign function interface (FFI) lets you call functions written in other languages (mostly C). The functions are declared in an extern "C" block. Since the compiler can't verify their signatures, the call is unsafe; since Rust 1.82 the block itself is also marked unsafe extern:

unsafe extern "C" {
    fn abs(x: i32) -> i32;      // from the C standard library
}

let n = unsafe { abs(-7) };   // 7

"C" specifies the calling convention (ABI): how arguments are passed and how the result returns.

A safe wrapper

Wrapping FFI calls in small safe functions gathers the unsafe in one place:

fn mutlak(x: i32) -> i32 {
    // SAFETY: abs is defined for every i32; no overflow except i32::MIN.
    unsafe { abs(x) }
}

The reverse direction is possible too: with #[no_mangle] pub extern "C" fn, Rust functions become callable from C. We'll look at FFI in detail in the next group.

Practice abs from C

Declare fn abs(x: i32) -> i32; in an unsafe extern "C" block and write a safe fn mutlak(x: i32) -> i32 wrapping it. Print the results of mutlak(-7) and mutlak(3) separated by a space.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
unsafe extern "C" {
    fn abs(x: i32) -> i32;
}

fn mutlak(x: i32) -> i32 {
    // SAFETY: abs her i32 için tanımlıdır.
    unsafe { abs(x) }
}

fn main() {
    println!("{} {}", mutlak(-7), mutlak(3));
}

Expected output

7 3

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What happens if the declared signature doesn't match the real C signature?

  • Compile error
  • Always a linker error
  • It's fixed automatically
  • Undefined behaviour; the compiler can't catch it Correct answer

Explanation: That's why declarations are usually generated from C header files with tools like bindgen.

2 Foreign block

Question
unsafe extern "____" {
    fn abs(x: i32) -> i32;
}
Answer
unsafe extern "C" {
    fn abs(x: i32) -> i32;
}

Explanation: The "C" calling convention is the ABI compatible with C functions.

3 Item and meaning

Term Meaning
extern "C" C calling convention
unsafe { abs(-7) } FFI call
#[no_mangle] Keeps the name
bindgen Generates declarations from headers

All lessons in Advanced