Foreign Function Interface

RustRustBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, we learn about Rust's Foreign Function Interface (FFI) that allows interaction with C libraries by declaring foreign functions within an extern block and annotating them with a #[link] attribute containing the name of the foreign library. The code example demonstrates the usage of FFI to call external functions from the libm library, such as computing the square root of a single precision complex number and calculating the cosine of a complex number. Safe wrappers are commonly used around these unsafe foreign function calls. The lab also includes a minimal implementation of single precision complex numbers and demonstrates how to call safe APIs wrapped around unsafe operations.

Note: If the lab does not specify a file name, you can use any file name you want. For example, you can use main.rs, compile and run it with rustc main.rs && ./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("`Rust`")) -.-> rust/BasicConceptsGroup(["`Basic Concepts`"]) rust(("`Rust`")) -.-> rust/DataTypesGroup(["`Data Types`"]) rust(("`Rust`")) -.-> rust/FunctionsandClosuresGroup(["`Functions and Closures`"]) rust(("`Rust`")) -.-> rust/MemorySafetyandManagementGroup(["`Memory Safety and Management`"]) rust(("`Rust`")) -.-> rust/AdvancedTopicsGroup(["`Advanced Topics`"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("`Variable Declarations`") rust/DataTypesGroup -.-> rust/floating_types("`Floating-point Types`") rust/DataTypesGroup -.-> rust/string_type("`String Type`") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("`Function Syntax`") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("`Expressions and Statements`") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("`Lifetime Specifiers`") rust/AdvancedTopicsGroup -.-> rust/traits("`Traits`") rust/AdvancedTopicsGroup -.-> rust/unsafe_rust("`Unsafe Rust`") subgraph Lab Skills rust/variable_declarations -.-> lab-99280{{"`Foreign Function Interface`"}} rust/floating_types -.-> lab-99280{{"`Foreign Function Interface`"}} rust/string_type -.-> lab-99280{{"`Foreign Function Interface`"}} rust/function_syntax -.-> lab-99280{{"`Foreign Function Interface`"}} rust/expressions_statements -.-> lab-99280{{"`Foreign Function Interface`"}} rust/lifetime_specifiers -.-> lab-99280{{"`Foreign Function Interface`"}} rust/traits -.-> lab-99280{{"`Foreign Function Interface`"}} rust/unsafe_rust -.-> lab-99280{{"`Foreign Function Interface`"}} end

Foreign Function Interface

Rust provides a Foreign Function Interface (FFI) to C libraries. Foreign functions must be declared inside an extern block annotated with a #[link] attribute containing the name of the foreign library.

use std::fmt;

// this extern block links to the libm library
#[link(name = "m")]
extern {
    // this is a foreign function
    // that computes the square root of a single precision complex number
    fn csqrtf(z: Complex) -> Complex;

    fn ccosf(z: Complex) -> Complex;
}

// Since calling foreign functions is considered unsafe,
// it's common to write safe wrappers around them.
fn cos(z: Complex) -> Complex {
    unsafe { ccosf(z) }
}

fn main() {
    // z = -1 + 0i
    let z = Complex { re: -1., im: 0. };

    // calling a foreign function is an unsafe operation
    let z_sqrt = unsafe { csqrtf(z) };

    println!("the square root of {:?} is {:?}", z, z_sqrt);

    // calling safe API wrapped around unsafe operation
    println!("cos({:?}) = {:?}", z, cos(z));
}

// Minimal implementation of single precision complex numbers
#[repr(C)]
#[derive(Clone, Copy)]
struct Complex {
    re: f32,
    im: f32,
}

impl fmt::Debug for Complex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < 0. {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

Summary

Congratulations! You have completed the Foreign Function Interface lab. You can practice more labs in LabEx to improve your skills.

Other Rust Tutorials you may like