Interfacing with C

Because of the vast functionality that exists in C code, it can sometimes be useful to delegate processing to a C routine, instead of writing everything in Rust.

You can call all functions and types from the C standard library by using the libc crate, which must be obtained through Cargo.

You have to add the following to Cargo.toml:

 [dependencies] 
    libc = "*" 

If you use Rust's nightly version, this is not necessary, but you have to use a feature attribute (or a feature gate, as they are also called) at the start of your code:

    #![feature(libc)]
Feature gates are common in Rust to enable the use of a certain functionality, but they are not available in stable Rust, only in the current development branch (nightly release).

If you have both the stable and nightly versions installed, you can easily switch between them using the commands rustup default nightly and rustup default stable.

Then, simply add the following to your Rust code:

extern crate libc; 

To import C functions and types, you can sum them up like this:

use libc::{c_void, size_t, malloc, free}; 

You can also use the wildcard * to make them all available, like in use libc::*;.

To work with C (or another language) from Rust, you will have to use the Foreign Function Interface (FFI); its utilities are in the std::ffi module. A foreign function interface is a mechanism by which a program written in one programming language can call routines or make use of services written in another language. But do realize that FFI calls cause significant overhead, so use them only when it is worth it.

Here is a simple example of calling C to print out a Rust String with the C function puts:

// code from Chapter 10/code/calling_libc.rs: 
extern crate libc;
use libc::puts;
use std::ffi::CString; fn main() { let sentence = "Merlin is the greatest magician!"; let to_print = CString::new(sentence).unwrap();
unsafe {
puts(to_print.as_ptr()); } }

This prints out the sentence:

Merlin is the greatest magician!

The new() method of CString will produce a C-compatible string (ending with 0 bytes) from the Rust String. The as_ptr() method returns a pointer to this C string.