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 comrustc 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.