CodeBlanks Logo Icon CodeBlanks

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.

Practice 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).

Starter code

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

Sample solution

main.rs
#[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));
}

Expected output

7

Questions and answers

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

1 What is <code>#[no_mangle]</code> for?

  • It stops the compiler from changing the symbol name, so C finds the function by name Correct answer
  • It hides the function
  • It inlines it
  • It turns off debugging

Explanation: 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)].

2 Exported function

Question
#[unsafe(no_mangle)]
pub ____ fn rs_topla(a: i32, b: i32) -> i32 {
    a + b
}
Answer
#[unsafe(no_mangle)]
pub extern "C" fn rs_topla(a: i32, b: i32) -> i32 {
    a + b
}

Explanation: A function called from C is defined with the C calling convention.

3 Group summary

Term Meaning
extern "C" { } Call C
#[repr(C)] C layout
CString/CStr String bridge
#[unsafe(no_mangle)] Offer to C

All lessons in Advanced