A foreign function interface (FFI) lets Rust call functions and use data types defined by non-Rust libraries. It connects Rust to C libraries through explicit declarations, compatible types, linking metadata, and carefully contained unsafe code. section 2.6 section 4.8
A practical Rust-to-C FFI typically requires:
- Declare external functions inside an extern "C" block using C-compatible types from libc. section 2.6
- Add a link attribute naming the native library, such as zlib, so rustc links the required symbols. section 2.6
- Wrap direct C calls in unsafe blocks and expose safer Rust-facing wrapper functions. section 2.6
- Represent shared C structs with #[repr(C)] and translated libc types rather than assuming ordinary Rust types are compatible. section 4.8
- Prefer rust-bindgen for larger headers; manually copy, convert, and declare simple interfaces when generation is disproportionate. section 4.8
Wrapping zlib compression
A Rust wrapper can allocate a destination buffer with compressBound, pass raw pointers and lengths to zlib's compress function, set the resulting vector length, and return Vec<u8>. A corresponding uncompress wrapper can round-trip “Hello, world!” and verify equality. section 2.6
type GzFile = *mut GzFileState;
#[link(name = "z")] #1
extern "C" { #2
fn gzopen(path: *const c_char, mode: *const c_char) -> GzFile; #2
fn gzread(file: GzFile, buf: *mut c_uchar, len: c_uint) -> c_int; #2
fn gzclose(file: GzFile) -> c_int; #2
fn gzeof(file: GzFile) -> c_int; #2
}
fn read_gz_file(name: &str) -> String {
let mut buffer = [0u8; 0x1000];
let mut contents = String::new();
unsafe {
let c_name = CString::new(name).expect("CString failed"); #3
let c_mode = CString::new("r").expect("CString failed");
let file = gzopen(c_name.as_ptr(), c_mode.as_ptr());
if file.is_null() {
panic!(
"Couldn’t read file: {}",
std::io::Error::last_os_error()
);
}
while gzeof(file) == 0 {
let bytes_read = gzread(
file,
buffer.as_mut_ptr(),
(buffer.len() - 1) as c_uint,
);
let s = std::str::from_utf8(&buffer[..(bytes_read as usize)])
.unwrap();
contents.push_str(s);
}
gzclose(file);
}
contents
}
This listing shows a complete C-struct mapping and function interface for opening, reading, and closing a gzip file through zlib. section 4.8

