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