Skip to content
Free public beta until December 4, 2026: every course is open, no card needed. After that, the first chapter of each course stays free and full access is a one-time $39 ($19 for up to 100 founding members chosen for helpful feedback). Your progress is kept. How the beta works

Recipe

Declare and call a C function from Rust

Use when: a Rust program needs a function from a C library, and you have its prototype from a header or its documentation

Goal: a correct declaration, called from one small safe Rust function

Taught in Calling C from Rust

  1. 1

    Find the function's prototype in the C header, such as size_t strlen(const char *s);.

    Example

    double hypot(double x, double y);

    Why: the header is the only source of truth for the ABI, and Rust will believe whatever you write.

  2. 2

    Replace every C type with its Rust match: c_int, c_double, usize for size_t, *const c_char for const char *.

    Example

    fn hypot(x: c_double, y: c_double) -> c_double; inside unsafe extern "C" { }.

    Why: only FFI-safe types have the size and layout C expects; the improper_ctypes lint catches the obvious misses.

  3. 3

    Mark it safe fn only if every possible argument value is valid input; otherwise leave it unsafe.

    Example

    safe fn hypot(...), but plain fn strlen(...), because a pointer can be bad.

    Why: a safe fn can be called from safe code, so it must not be able to cause undefined behavior.

  4. 4

    Write a safe Rust function whose parameter types guarantee the C function's requirements, with a // SAFETY: comment on the unsafe block.

    Example

    fn c_len(s: &CStr) -> usize { unsafe { strlen(s.as_ptr()) } }

    Why: the rest of the program then calls safe Rust, and the unsafe reasoning lives in one place.

Common mistakes

  • Guessing a type (i64 for long, &str for const char *) instead of copying it from the header.
  • Marking a function safe fn because it seemed harmless for the arguments you had in mind.
  • Forgetting that the declaration doesn't bring in the library: a function outside the C library needs #[link] or a build script.