Rust — un lenguaje de programación de sistemas con garantías de seguridad de memoria en tiempo de compilación. Desarrollado por Mozilla Research en 2010 bajo la dirección de Graydon Hoare. Rust previene clases enteras de vulnerabilidades: punteros nulos, referencias colgantes y condiciones de carrera. En el desarrollo móvil, Rust se utiliza para módulos nativos, SDK multiplataforma y WebAssembly. Según Stack Overflow Survey (2025), Rust ha sido el «lenguaje más querido» durante nueve años consecutivos.
Puntos clave
Rust es un lenguaje de programación de sistemas tipado estáticamente con abstracciones de costo cero. Rust garantiza la seguridad de memoria sin un recolector de basura gracias a su sistema de propiedad (ownership), préstamo (borrowing) y tiempos de vida (lifetimes). El compilador de Rust es uno de los más estrictos: rechaza código que causaría comportamiento indefinido en C++.
Rust se compila mediante LLVM a código nativo para todas las arquitecturas: ARM, x86, RISC-V, WebAssembly. El conjunto de herramientas incluye: rustup (instalador), rustc (compilador), cargo (gestor de paquetes y construcción). Cargo.toml — similar a package.json, contiene dependencias de crates.io. La versión estable más reciente es Rust 1.81 (2025).
Áreas clave de aplicación de Rust en el desarrollo móvil: bibliotecas nativas (Android NDK, iOS), SDK multiplataforma (Firefox, Dropbox), reemplazo de C++ en secciones críticas de rendimiento, WebAssembly para aplicaciones híbridas. Google usa Rust en AOSP (Android Open Source Project) para componentes de Bluetooth, Wi-Fi y NFC.
Para la compilación cruzada a Android, se necesitan toolchains de destino: rustup target add aarch64-linux-android armv7-linux-androideabi. Para iOS — aarch64-apple-ios x86_64-apple-ios. cargo-ndk (para Android) y cargo-lipo (para iOS) simplifican el proceso de compilación.
# Instalación de Rust y plataformas de destino para desarrollo móvil
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ rustup target add aarch64-linux-android
$ rustup target add armv7-linux-androideabi
$ rustup target add aarch64-apple-ios
$ rustup target add x86_64-apple-ios
# Instalación de cargo-ndk para compilación en Android
$ cargo install cargo-ndk
# Compilación para Android
$ cargo ndk -t arm64-v8a -o ./jniLibs build --releaseOwnership (propiedad) es el concepto fundamental de Rust. Cada valor tiene exactamente un dueño. Al asignarse o pasarse a una función, la propiedad se transfiere (move). Después de una transferencia, el antiguo dueño no puede usar el valor. Esto elimina la doble liberación de memoria y los punteros colgantes.
Borrowing (préstamo) permite usar temporalmente una referencia a un valor sin transferir la propiedad. La referencia &T (inmutable) — cualquier número de lectores. La referencia &mut T (mutable) — exactamente un escritor, sin lectores. El compilador verifica estas reglas en tiempo de compilación.
fn process_data(data: &mut Vec<i32>) {
for item in data.iter_mut() {
*item *= 2;
}
}
fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
process_data(&mut numbers);
println!("Processed: {:?}", numbers);
let first = &numbers[0]; // préstamo inmutable
println!("First: {}", first);
}process_data toma una referencia mutable a Vec y duplica cada elemento. iter_mut() devuelve un iterador con referencias mutables. *item desreferencia la referencia para la asignación. Después de process_data, numbers sigue siendo accesible — la propiedad no se transfirió, solo se prestó.
Lifetimes ('a) — anotaciones que vinculan los tiempos de vida de las referencias. El compilador las usa para verificar que una referencia no sobreviva a los datos a los que apunta. En la mayoría de los casos, los lifetimes se infieren automáticamente — solo es necesario especificarlos en firmas de funciones con referencias.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
fn main() {
let string1 = String::from("rust");
let result;
{
let string2 = String::from("mobile");
result = longest(string1.as_str(), string2.as_str());
println!("Longest: {}", result);
} // string2 vive hasta esta llave, result es válido dentro
// println!("{}", result); // error: string2 ha muerto
}Rust se compila en bibliotecas nativas para Android (.so mediante NDK) e iOS (.a bibliotecas estáticas). Google admite oficialmente Rust en Android Open Source Project (AOSP) — Rust se usa para componentes de Bluetooth (ava), DNS-over-HTTP3 y CriticalNotification. Según Google (2025), Rust en Android eliminó el 70% de las vulnerabilidades de memoria en componentes específicos.
Para Android se usa cargo-ndk, que envuelve Cargo con el toolchain correcto para el ABI seleccionado. La compilación para Android incluye: aarch64-linux-android (ARM de 64 bits, dispositivos modernos), armv7-linux-androideabi (ARM de 32 bits), x86_64-linux-android (emuladores).
// Cargo.toml — configuración de biblioteca para Android/iOS
[package]
name = "mobile_crypto"
version = "0.1.0"
[lib]
crate-type = ["staticlib", "cdylib"]
[dependencies]
serde = { version = "1", features = ["derive"] }
libc = "0.2"crate-type: staticlib — para iOS (.a), cdylib — para Android (.so). serde — serialización para intercambio de datos con Kotlin/Swift. libc — tipos compatibles con C para FFI.
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
/// Función compatible con C para procesamiento de imágenes
#[no_mangle]
pub unsafe extern "C" fn process_image(
input: *const u8,
len: usize,
output: *mut u8,
out_len: *mut usize,
) {
let input_slice = std::slice::from_raw_parts(input, len);
let result: Vec<u8> = input_slice.iter()
.map(|b| b ^ 0xFF)
.collect();
let result_len = result.len();
std::ptr::copy_nonoverlapping(result.as_ptr(), output, result_len);
*out_len = result_len;
}#[no_mangle] desactiva el name mangling para un ABI compatible con C. extern "C" especifica la convención de llamada de C. unsafe — un marcador que indica que una llamada desde fuera de Rust no garantiza seguridad. std::ptr::copy_nonoverlapping copia los bytes del resultado al búfer de salida.
Rust es el candidato ideal para SDK multiplataforma que funcionan en Android e iOS desde un solo código base. Empresas como Mozilla (Firefox), Dropbox (sincronización de archivos) y Meta (blockchain Libra) eligieron Rust para componentes críticos de sus aplicaciones móviles.
Ventajas de las bibliotecas Rust sobre C++: el compilador garantiza la ausencia de fugas de memoria y condiciones de carrera en el código multiplataforma. El código escrito y probado en Rust funciona de manera idéntica en todas las plataformas. Cargo gestiona las dependencias de forma nativa, sin CMake ni vcpkg.
| Biblioteca/Crate | Propósito |
|---|---|
| tonic | Cliente/servidor gRPC en Rust |
| reqwest | Cliente HTTP con async/await |
| ring | Criptografía (AES, RSA, ECDSA) |
| sqlx | SQLite y PostgreSQL asíncronos |
| wasm-bindgen | Integración Rust con JavaScript/WASM |
| ndk-glue | Android NativeActivity en Rust |
| uniffi | Generación de enlaces FFI para Kotlin/Swift |
Rust se compila a WebAssembly (Wasm) — un formato binario ejecutable en el navegador y en dispositivos móviles. Wasm ofrece un rendimiento casi nativo en entornos web. En el desarrollo móvil, Wasm se usa en aplicaciones híbridas (WebView + Wasm) para cálculos complejos: renderizado 3D, reconocimiento de imágenes, cifrado.
wasm-pack compila Rust a .wasm y genera un envoltorio JS. wasm-bindgen conecta funciones de Rust con llamadas de JavaScript. En un dispositivo móvil, el ejecutor Wasm puede funcionar en WebView o mediante el SDK de Wasmer/Wasmtime.
use wasm_bindgen::prelude::*;
/// Cálculo de números de Fibonacci en Wasm (llamado desde JS)
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
}
}#[wasm_bindgen] genera un envoltorio JavaScript para la función fibonacci. En el navegador, la llamada se ve como wasm.fibonacci(10). Los tipos u32/u64 se convierten automáticamente a Number/BigInt. El módulo Wasm pesa solo ~5 KB para tal función — una sobrecarga mínima.
FFI (Foreign Function Interface) — un mecanismo para llamar código Rust desde otros lenguajes. Las funciones Rust con extern "C" y #[no_mangle] se exportan con un ABI compatible con C. Desde Kotlin, estas funciones se llaman mediante JNI, desde Swift — mediante @_cdecl ("name") o CBridge.h.
UniFFI — una herramienta de Mozilla para generar enlaces FFI. Se describe la API en un archivo .udl, y UniFFI genera envoltorios Kotlin y Swift automáticamente. Este es el enfoque estándar para componentes Rust en Firefox Android y Firefox iOS.
// Biblioteca Rust con interfaz UniFFI
uniffi::setup_scaffolding!();
#[derive(uniffi::Enum)]
pub enum EncryptionError {
InvalidKey,
EncryptionFailed,
}
#[derive(uniffi::Record)]
pub struct EncryptedData {
pub ciphertext: Vec<u8>,
pub nonce: Vec<u8>,
}
#[uniffi::export]
pub fn encrypt(key: &[u8], plaintext: &[u8]) -> Result<EncryptedData, EncryptionError> {
// implementación AES-256-GCM
todo!()
}UniFFI genera una clase Kotlin con el método encrypt, que toma un ByteArray y devuelve EncryptedData. En Swift, se crea una estructura EncryptedData con los campos ciphertext (Data) y nonce (Data). Los errores se convierten en excepciones de Kotlin/Swift.
Rust y C++ son los dos lenguajes principales para la programación de sistemas en el desarrollo móvil. Ambos se compilan a código nativo para ARM y admiten FFI mediante el ABI de C. La diferencia clave es el modelo de seguridad de memoria: Rust la verifica en tiempo de compilación, C++ depende de la disciplina del desarrollador.
| Criterio | Rust | C++ |
|---|---|---|
| Seguridad de memoria | Garantizada (ownership) | Responsabilidad del desarrollador |
| Recolector de basura | No (RAII + ownership) | No (gestión manual) |
| Fugas de memoria | Prevenidas por el compilador | Posibles (new sin delete) |
| Condiciones de carrera | Prevenidas (Send + Sync) | Posibles |
| Android NDK | Mediante cargo-ndk | Mediante CMake / NDK Build |
| Soporte iOS | cargo-lipo + .a | Xcode + .a |
| Sistema de compilación | Cargo (integrado) | CMake / Ninja |
| Tiempo de compilación | 2–5 min (limpio) | 5–15 min (limpio) |
| Ecosistema | crates.io (200k+ crates) | vcpkg / Conan (100k+ bibliotecas) |
Rust es más seguro que C++ y más productivo — el compilador detecta errores que se manifestarían en tiempo de ejecución en C++. C++ tiene un ecosistema de bibliotecas móviles más rico. Para proyectos nuevos, Rust es preferible; el código C++ existente se migra gradualmente.
Preguntas frecuentes
La principal diferencia es la seguridad de memoria en tiempo de compilación. Rust no tiene nullptr, punteros colgantes ni condiciones de carrera gracias a su sistema de propiedad y borrow checker. C++ depende de la disciplina del desarrollador, Rust depende de las verificaciones del compilador.
Sí, mediante Android NDK. Google admite oficialmente Rust en AOSP (Android Open Source Project). Rust se compila en bibliotecas .so mediante cargo-ndk. FFI (Foreign Function Interface) a través de JNI funciona igual que para C++.
Cargo es el gestor de paquetes y sistema de compilación de Rust. Descarga dependencias de crates.io, compila el proyecto y ejecuta pruebas. En el desarrollo móvil, cargo-ndk extiende Cargo para la compilación cruzada a ABI de Android.
Rust admite ambas plataformas. Para iOS se usa cargo-lipo para crear binarios universales (arm64 + x86_64 simulador). El código Rust se compila en una biblioteca estática .a y se enlaza mediante Xcode.
Sí, Rust se está convirtiendo en el estándar para SDK multiplataforma y módulos nativos. Google, Meta y Mozilla están invirtiendo en Rust. Para componentes críticos de rendimiento, Rust es más seguro y productivo que C++.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también