extern block
- Rust course
- Advanced
- Lesson 36/81
- 4 min
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
use std::ffi::c_int;
fn main() {
// buraya yaz
}Sample solution
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
unsafe extern "C" {
fn toupper(c: ____) -> c_int;
}
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 |