Interface de Função Estrangeira

Beginner

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

Introdução

Neste laboratório, aprendemos sobre a Interface de Função Estrangeira (FFI) do Rust, que permite a interação com bibliotecas C declarando funções estrangeiras dentro de um bloco extern e anotando-as com um atributo #[link] contendo o nome da biblioteca estrangeira. O exemplo de código demonstra o uso da FFI para chamar funções externas da biblioteca libm, como calcular a raiz quadrada de um número complexo de precisão única e calcular o cosseno de um número complexo. Geralmente, são usados wrappers seguros em torno dessas chamadas de funções estrangeiras inseguras. O laboratório também inclui uma implementação mínima de números complexos de precisão única e demonstra como chamar APIs seguras envolvendo operações inseguras.

Nota: Se o laboratório não especificar um nome de arquivo, você pode usar qualquer nome de arquivo que desejar. Por exemplo, você pode usar main.rs, compilar e executá-lo com rustc main.rs && ./main.

Interface de Função Estrangeira

O Rust fornece uma Interface de Função Estrangeira (FFI) para bibliotecas C. As funções estrangeiras devem ser declaradas dentro de um bloco extern anotado com um atributo #[link] contendo o nome da biblioteca estrangeira.

use std::fmt;

// este bloco extern faz ligação com a biblioteca libm
#[link(name = "m")]
extern {
    // esta é uma função estrangeira
    // que calcula a raiz quadrada de um número complexo de precisão única
    fn csqrtf(z: Complex) -> Complex;

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

// Como chamar funções estrangeiras é considerado inseguro,
// é comum criar wrappers seguros em torno delas.
fn cos(z: Complex) -> Complex {
    unsafe { ccosf(z) }
}

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

    // chamar uma função estrangeira é uma operação insegura
    let z_sqrt = unsafe { csqrtf(z) };

    println!("a raiz quadrada de {:?} é {:?}", z, z_sqrt);

    // chamando API segura envolvendo operação insegura
    println!("cos({:?}) = {:?}", z, cos(z));
}

// Implementação mínima de números complexos de precisão única
#[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)
        }
    }
}

Resumo

Parabéns! Você concluiu o laboratório de Interface de Função Estrangeira. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.