La Interfaz de Función Extranjera (FFI, por sus siglas en inglés) en Rust permite que el código Rust interactúe con código escrito en otros lenguajes de programación, como C. Esto es especialmente útil cuando necesitas utilizar bibliotecas existentes escritas en otros lenguajes o cuando deseas optimizar ciertas partes de tu aplicación con código de bajo nivel.

Conceptos Clave

  1. extern: La palabra clave extern se utiliza para declarar funciones y bloques de código que se implementan en otros lenguajes.
  2. unsafe: Interactuar con código externo puede ser inseguro, por lo que muchas operaciones FFI requieren el uso de bloques unsafe.
  3. libc: Una biblioteca comúnmente utilizada para FFI en Rust que proporciona bindings a las funciones de la biblioteca estándar de C.

Declarando Funciones Externas

Para llamar a una función escrita en C desde Rust, primero debes declarar la función utilizando la palabra clave extern. Aquí hay un ejemplo simple:

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

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

Explicación del Código

  • extern "C": Indica que la función sigue el ABI (Application Binary Interface) de C.
  • fn printf(format: *const i8, ...) -> i32: Declara la función printf de C, que toma un puntero a un i8 (cadena de caracteres) y una lista de argumentos variables, y devuelve un i32.
  • b"Hello from Rust!\0".as_ptr() as *const i8: Convierte una cadena de Rust a un puntero de C (*const i8).
  • unsafe: Llama a la función printf dentro de un bloque unsafe porque interactuar con código externo es potencialmente inseguro.

Llamando a Funciones de Rust desde C

Para que el código C pueda llamar a funciones de Rust, debes exportar las funciones de Rust utilizando #[no_mangle] y extern "C".

Ejemplo

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

Código C para Llamar a la Función Rust

#include <stdio.h>

extern int add(int a, int b);

int main() {
    int result = add(5, 3);
    printf("Result: %d\n", result);
    return 0;
}

Ejercicio Práctico

Ejercicio

  1. Escribe una función en C que multiplique dos números enteros.
  2. Declara y llama a esta función desde Rust.

Solución

Código C (guardar como multiply.c)

#include <stdio.h>

int multiply(int a, int b) {
    return a * b;
}

Código Rust

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

fn main() {
    let a = 6;
    let b = 7;
    let result;
    unsafe {
        result = multiply(a, b);
    }
    println!("Result: {}", result);
}

Compilación y Ejecución

  1. Compila el archivo C:

    gcc -c multiply.c -o multiply.o
    gcc -shared -o libmultiply.so multiply.o
    
  2. Compila y ejecuta el archivo Rust:

    rustc main.rs -L . -l multiply
    ./main
    

Resumen

En esta sección, aprendiste cómo utilizar la Interfaz de Función Extranjera (FFI) en Rust para interactuar con código escrito en otros lenguajes, como C. Vimos cómo declarar y llamar a funciones externas, así como cómo exportar funciones de Rust para que puedan ser llamadas desde C. Practicar estos conceptos te permitirá aprovechar bibliotecas existentes y optimizar tu código Rust con funciones de bajo nivel.

En el siguiente módulo, exploraremos cómo construir un proyecto completo en Rust, incluyendo pruebas y documentación.

© Copyright 2024. Todos los derechos reservados