- Cpp2Rust es un traductor guiado por sintaxis basado en el AST de clang, que convierte automáticamente entradas en C++ a código Rust completamente seguro
- El proceso de traducción parsea los archivos C++ con clang para crear un AST, recorre el AST generando código Rust como cadenas y luego usa
rustfmt para producir un único archivo .rs
- El valor predeterminado es el modelo de conteo de referencias, y también es posible generar Rust unsafe con
--model=unsafe para depuración y comparación de rendimiento
- El código generado depende de la biblioteca de runtime
libcc2rs, y los punteros de C se convierten en Ptr<T>, que modela null, aritmética de punteros y aliasing
- Para traducir programas completos se requiere
compile_commands.json, y en proyectos CMake se puede generar con la bandera CMAKE_EXPORT_COMPILE_COMMANDS=ON
Conversión automática de C++ a Rust seguro
- Cpp2Rust es una herramienta que traduce automáticamente C++ a Rust completamente seguro
- Es un traductor guiado por sintaxis basado en el AST de clang
- El algoritmo de traducción se describe en el artículo Cpp2Rust: Automatic Translation of C++ to Safe Rust, publicado en PLDI 2026
Pipeline de traducción
- Primero parsea el archivo C++ de entrada con clang para generar un AST
- Luego recorre el AST y emite el código Rust como una cadena
- Cuando es necesario, inserta llamadas a la biblioteca de runtime
libcc2rs
- Un ejemplo es el manejo de semántica de raw pointers
- Por último, usa
rustfmt para ordenar el código Rust en un único archivo .rs
Modelos de Rust seguro y Rust unsafe
- El comportamiento predeterminado usa el modelo de conteo de referencias y genera una salida en Rust completamente seguro
- También se ofrece un generador de Rust unsafe
- El argumento de línea de comandos es
--model=unsafe
- Su uso es para depuración y comparación de rendimiento
Biblioteca de runtime libcc2rs
- El código generado depende de una biblioteca de runtime diseñada para simplificar el proceso de traducción
- Los punteros de C se convierten al tipo
Ptr<T> provisto por libcc2rs
Ptr<T> modela la semántica de los punteros de C
- null
- aritmética de punteros
- aliasing
- El borrow checker de Rust se satisface mediante operaciones de runtime verificadas
Flujo de compilación y ejecución
- Un ejemplo de instalación de dependencias en Ubuntu incluye
libclang-22-dev, clang++-22, ninja-build, cmake y ruff
- La compilación sigue el orden
cmake -GNinja .., ninja, ninja check
- El comando para traducir un solo archivo tiene la siguiente forma
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs
- Para generar Rust unsafe, se ejecuta así
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs --model=unsafe
Ejemplo mínimo y traducción de programas completos
- El ejemplo
printf("hello world\n") de hello.cpp se convierte en código que incluye println!("hello world") de Rust
- El
hello.rs convertido se compila y ejecuta así
rustc hello.rs -L ../libcc2rs/target/debug
./hello
- Para traducir programas completos se requiere
compile_commands.json
- En CMake,
compile_commands.json se genera con la siguiente bandera
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
- El comando para traducir un programa completo tiene la siguiente forma
./build/cpp2rust/cpp2rust --dir=<dir> -o <output>.rs
<dir> debe ser el directorio que contiene compile_commands.json
Comandos de prueba
- Todas las pruebas se ejecutan con
ninja check
- Las pruebas unitarias se ejecutan con
ninja check-unit
- Las pruebas unitarias de
libcc2rs se ejecutan con ninja check-libcc2rs
- Las pruebas unitarias de
libcc2rs-macros se ejecutan con ninja check-libcc2rs-macros
- Para regenerar la salida esperada tras hacer cambios intencionales, se usa
REPLACE_EXPECTED=1 ninja check-unit
1 comentarios
Opiniones en Lobste.rs
Escuché una charla de Dan Wallach en febrero de este año, donde presentó el proyecto TRACTOR (Translating All C to Rust) de DARPA [1] [2] [3]
Al parecer, el equipo de MIT Lincoln Laboratory está realizando las pruebas y evaluaciones del programa de investigación
Entiendo que todavía está en etapa de investigación, pero me interesa mucho este tema y tengo bastante curiosidad por ver qué tipo de herramientas e ideas salen de aquí
Parece que realmente podría eliminar muchos de esos bugs “menores” que vienen del manejo de memoria
[1] https://www.darpa.mil/research/programs/translating-all-c-to-rust
[2] https://github.com/DARPA-TRACTOR-Program
[3] https://ll.mit.edu/r-d/projects/…
Interesante. Estaría muy bien poder ver una o dos demos de librerías o apps que los autores hayan convertido con esto y que ellos mismos consideren interesantes
Por ejemplo, si ves https://github.com/Cpp2Rust/cpp2rust-testsuite/…, podrá ser Rust seguro, pero claramente cuesta llamarlo Rust idiomático
No termino de entender por qué hace falta una etapa de conversión. Si hay suficiente información como para convertirlo a Rust con seguridad de memoria, ¿no significa eso que también habría suficiente información como para garantizar por análisis estático que el C++ es seguro?
Dice que alrededor del 70% de las vulnerabilidades de seguridad en software ampliamente distribuido provienen de bugs de seguridad de memoria en lenguajes como C y C++, y que, pese a décadas de inversión en mitigaciones como análisis estático, sanitizers y aislamiento por hardware, los atacantes siguen explotando operaciones de memoria inseguras
Explica que una solución prometedora a largo plazo es migrar los codebases existentes de C++ a un lenguaje con seguridad de memoria como Rust, pero hacerlo a mano es demasiado costoso y propenso a errores
Cpp2Rust afirma ser el primer sistema capaz de traducir automáticamente programas en C++ a código Rust funcionalmente equivalente y con seguridad de memoria
A cambio de sacrificar algo de rendimiento por seguridad, resuelve la incompatibilidad fundamental entre las referencias con alias sin restricciones de C++ y el modelo de ownership de Rust insertando verificaciones en runtime de ownership y mutabilidad, preservando la semántica y garantizando la seguridad
Para reducir el overhead de las verificaciones dinámicas, también crearon optimizaciones interprocedimentales para el código Rust, eliminando operaciones de ownership redundantes y recuperando buena parte del rendimiento perdido
Así que la motivación no es simplemente demostrar seguridad, sino migrarlo a Rust y facilitar que el desarrollo futuro también se mueva a Rust
La idea de proyectos como este es crear un punto de partida para seguir refactorizando hacia Rust idiomático, y así volver el código analizable
Con suerte, eso también permitirá eliminar verificaciones en runtime o partes inseguras del código traducido
Se podría decir que bastaría con refactorizar C++ para que tenga “forma de Rust” y así hacerlo igual de analizable, pero C++ tiene otra semántica que permite mucha más flexibilidad, así que las rutas a analizar pueden crecer exponencialmente o el análisis estático puede terminar en callejones ambiguos
Habría que prometer no hacer cosas difíciles para los analizadores estáticos ni explotar casos límite, y para eso podrías crear un dialecto de C++ con semántica más restringida y anotaciones extra
Circle/Safe C++ mostró que eso tenía potencial, pero el WG de C++ rechazó con fuerza esa dirección, así que solo queda elegir entre usar por tu cuenta un dialecto de C++ parecido a Rust pero sin respaldo, o simplemente usar Rust
¿Cómo funciona exactamente si el código de entrada en sí no es seguro?