💻 Exemplos: Capítulo 19: Unsafe Rust, Ponteiros Brutos e FFI (C Interop)
💻 Exemplos: Capítulo 19: Unsafe Rust, Ponteiros Brutos e Interoperabilidade C (FFI)
Especialização em Sistemas com Rust • Demonstrações Práticas Compiláveis
🎯 Objetivo dos Exemplos
Explorar com responsabilidade e rigor os recursos de Unsafe Rust: criação e desreferenciação de ponteiros brutos (raw pointers *const T e *mut T), chamada de funções externas da linguagem C (Foreign Function Interface - FFI) e o princípio sagrado da engenharia em Rust: encapsular blocos unsafe dentro de APIs públicas 100% seguras.
1. Código Fonte Completo (src/main.rs)
//! Unsafe Rust, Ponteiros Brutos, Desreferenciação e FFI com C
// Declaração de funções externas em C da libc nativa do sistema
extern "C" {
// Função da libc: int abs(int j);
fn abs(input: i32) -> i32;
// Função da libc: size_t strlen(const char *s);
fn strlen(s: *const u8) -> usize;
}
/// Abstração Segura em torno de manipulação de memória de baixo nível
pub struct BufferAlinhado {
ptr: *mut u8,
capacidade: usize,
}
impl BufferAlinhado {
pub fn alocar(capacidade: usize) -> Self {
let mut vetor = Vec::with_capacity(capacidade);
let ptr = vetor.as_mut_ptr();
std::mem::forget(vetor); // Impede que o Vec libere a memória no final da função
Self { ptr, capacidade }
}
pub fn escrever_byte(&mut self, indice: usize, valor: u8) -> Result<(), &'static str> {
if indice >= self.capacidade {
return Err("Índice fora dos limites do buffer!");
}
// Bloco unsafe delimitado e estritamente protegido por checagem de limites
unsafe {
// Aritmética de ponteiros brutos e escrita direta
let destino = self.ptr.add(indice);
*destino = valor;
}
Ok(())
}
pub fn ler_byte(&self, indice: usize) -> Result<u8, &'static str> {
if indice >= self.capacidade {
return Err("Índice fora dos limites do buffer!");
}
unsafe {
let endereco = self.ptr.add(indice);
Ok(*endereco)
}
}
}
// Implementação segura de liberação (RAII) para evitar memory leaks do buffer unsafe
impl Drop for BufferAlinhado {
fn drop(&mut self) {
unsafe {
// Reconstrói o Vec temporariamente para permitir a desalocação segura
let _vetor_para_liberar = Vec::from_raw_parts(self.ptr, 0, self.capacidade);
println!(" [UNSAFE/DROP] Memória bruta do buffer desalocada com segurança.");
}
}
}
fn main() {
println!("=== UNSAFE RUST E FOREIGN FUNCTION INTERFACE (FFI) ===");
// 1. Criação e Desreferenciação de Ponteiros Brutos (Raw Pointers)
let mut numero: i32 = 42;
// A criação de ponteiros brutos é 100% segura e não exige unsafe
let ptr_imutavel: *const i32 = &numero as *const i32;
let ptr_mutavel: *mut i32 = &mut numero as *mut i32;
println!("Endereço do ponteiro bruto imutável: {:p}", ptr_imutavel);
println!("Endereço do ponteiro bruto mutável: {:p}", ptr_mutavel);
// APENAS a desreferenciação (leitura/escrita no endereço) exige o bloco unsafe
unsafe {
println!("Leitura através de *ptr_imutavel: {}", *ptr_imutavel);
*ptr_mutavel += 58; // Mutação direta na memória bruta
println!("Novo valor lido através de *ptr_mutavel: {}", *ptr_mutavel);
}
println!("Valor final na variável original: {}", numero);
// 2. Invocando Funções Externas C (FFI)
println!("\nInvocando funções nativas da libc em C via FFI:");
let valor_negativo: i32 = -1024;
// Funções FFI são sempre 'unsafe' porque o Rust não pode garantir o que o C faz
let valor_absoluto = unsafe { abs(valor_negativo) };
println!("C abs({}) = {}", valor_negativo, valor_absoluto);
let mensagem_c = b"RustBareMetal\0"; // String terminada em nulo para C
let tamanho_string = unsafe { strlen(mensagem_c.as_ptr()) };
println!("C strlen(\"RustBareMetal\") = {} caracteres", tamanho_string);
// 3. Abstração Segura em Ação
println!("\nTestando abstração de Buffer Seguro:");
{
let mut buffer = BufferAlinhado::alocar(8);
buffer.escrever_byte(0, 0xAA).unwrap();
buffer.escrever_byte(1, 0xBB).unwrap();
println!("Byte lido no índice 0: 0x{:X}", buffer.ler_byte(0).unwrap());
println!("Byte lido no índice 1: 0x{:X}", buffer.ler_byte(1).unwrap());
println!("Tentativa fora dos limites: {:?}", buffer.ler_byte(10));
}
println!("Escopo encerrado.");
}
2. Saída Esperada no Terminal
=== UNSAFE RUST E FOREIGN FUNCTION INTERFACE (FFI) ===
Endereço do ponteiro bruto imutável: 0x7fff489b04fc
Endereço do ponteiro bruto mutável: 0x7fff489b04fc
Leitura através de *ptr_imutavel: 42
Novo valor lido através de *ptr_mutavel: 100
Valor final na variável original: 100
Invocando funções nativas da libc em C via FFI:
C abs(-1024) = 1024
C strlen("RustBareMetal") = 13 caracteres
Testando abstração de Buffer Seguro:
Byte lido no índice 0: 0xAA
Byte lido no índice 1: 0xBB
Tentativa fora dos limites: Err("Índice fora dos limites do buffer!")
[UNSAFE/DROP] Memória bruta do buffer desalocada com segurança.
Escopo encerrado.