CodeBlanks Logo Icon CodeBlanks

extern block

Declare C functions with extern "C".

The extern block

Functions from C libraries are declared in an extern "C" block. For C types, use the aliases from std::ffi and std::os::raw: C's int may not be Rust's i32 on every platform:

use std::ffi::c_int;

unsafe extern "C" {
    fn toupper(c: c_int) -> c_int;
}

let buyuk = unsafe { toupper('a' as c_int) } as u8 as char;   // 'A'

The standard C library (libc) is already linked. For another library, the #[link(name = "z")] attribute or a build.rs script is used.

Linking

The declaration only gives the signature; the function body is found at link time. If it isn't found, the error comes not at compile time but from the linker: "undefined reference to ...". Static or dynamic linking can be chosen:

#[link(name = "sqlite3")]              // libsqlite3.so / sqlite3.lib
unsafe extern "C" {
    fn sqlite3_libversion() -> *const std::ffi::c_char;
}

For ready-made bindings, crates with a -sys suffix (e.g. libsqlite3-sys) are used; safe wrapper crates are built on top of them.

Practice Calling toupper

Declare C's toupper function in an unsafe extern "C" block. Uppercase the characters 'a' and 'z' and print the results as char separated by a space.

Starter code

main.rs
use std::ffi::c_int;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::ffi::c_int;

unsafe extern "C" {
    fn toupper(c: c_int) -> c_int;
}

fn buyut(c: char) -> char {
    // SAFETY: toupper her ASCII değeri için tanımlıdır.
    (unsafe { toupper(c as c_int) }) as u8 as char
}

fn main() {
    println!("{} {}", buyut('a'), buyut('z'));
}

Expected output

A Z

Questions and answers

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

1 Which Rust type should be used for C's <code>long</code>?

  • isize
  • std::ffi::c_long Correct answer
  • Always i64
  • Always i32

Explanation: long is 64 bits on 64-bit Linux and 32 on Windows; c_long picks the right type for the platform.

2 C integer

Question
unsafe extern "C" {
    fn toupper(c: ____) -> c_int;
}
Answer
unsafe extern "C" {
    fn toupper(c: c_int) -> c_int;
}

Explanation: C's int type is expressed as std::ffi::c_int in Rust.

3 C type and Rust counterpart

Term Meaning
int c_int
long c_long
char * *const c_char
void * *mut c_void

All lessons in Advanced