Introducció

La Interfície de Funció Estrangera (FFI) permet que el codi escrit en Rust interactuï amb codi escrit en altres llenguatges de programació, com C o C++. Això és especialment útil quan es vol reutilitzar biblioteques existents o integrar Rust en projectes més grans que ja utilitzen altres llenguatges.

Conceptes Clau

  1. Exposició de Funcions Rust a C: Permet que el codi C cridi funcions definides en Rust.
  2. Crida de Funcions C des de Rust: Permet que el codi Rust cridi funcions definides en C.
  3. Tipus de Dades Compatibles: Assegura que els tipus de dades utilitzats en les interfícies siguin compatibles entre Rust i el llenguatge estranger.
  4. Seguretat: L'ús de FFI pot introduir riscos de seguretat, per la qual cosa és important seguir bones pràctiques.

Exposició de Funcions Rust a C

Per exposar funcions Rust a C, utilitzem l'atribut #[no_mangle] i la paraula clau extern "C".

Exemple

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

Explicació

  • #[no_mangle]: Evita que el compilador canviï el nom de la funció, permetent que sigui accessible des de C.
  • extern "C": Indica que la funció utilitza la convenció de crida de C.

Crida de Funcions C des de Rust

Per cridar funcions C des de Rust, utilitzem la paraula clau extern i definim les funcions externes.

Exemple

extern "C" {
    fn printf(format: *const i8, ...) -> i32;
}

fn main() {
    let message = b"Hello from Rust!\0" as *const u8 as *const i8;
    unsafe {
        printf(message);
    }
}

Explicació

  • extern "C": Indica que les funcions declarades utilitzen la convenció de crida de C.
  • unsafe: Les crides a funcions externes són insegures perquè el compilador no pot verificar la seva seguretat.

Tipus de Dades Compatibles

Quan es treballa amb FFI, és important assegurar-se que els tipus de dades utilitzats són compatibles entre Rust i el llenguatge estranger. Alguns tipus comuns són:

Rust C
i32 int
u32 unsigned int
f32 float
f64 double
*const T const T*
*mut T T*

Exercici Pràctic

Exercici

  1. Escriu una funció en C que sumi dos enters.
  2. Escriu un programa en Rust que cridi aquesta funció C i imprimeixi el resultat.

Solució

Codi C

// sum.c
int sum(int a, int b) {
    return a + b;
}

Codi Rust

extern "C" {
    fn sum(a: i32, b: i32) -> i32;
}

fn main() {
    let result = unsafe { sum(5, 3) };
    println!("The sum is: {}", result);
}

Compilació i Execució

  1. Compila el codi C:
    gcc -c sum.c -o sum.o
    
  2. Compila el codi Rust i enllaça amb l'objecte C:
    rustc main.rs sum.o -o main
    
  3. Executa el programa:
    ./main
    

Resum

En aquesta secció, hem après com utilitzar la Interfície de Funció Estrangera (FFI) per permetre que el codi Rust interactuï amb codi escrit en altres llenguatges, com C. Hem vist com exposar funcions Rust a C, com cridar funcions C des de Rust, i la importància d'utilitzar tipus de dades compatibles. També hem realitzat un exercici pràctic per reforçar aquests conceptes.

© Copyright 2024. Tots els drets reservats