Cpp2Rust: Automatic Translation of C++ to Safe Rust

Cpp2Rust: Automatic Translation of C++ to Safe Rust

Cpp2Rust:将 C++ 自动转换为安全 Rust 的工具

Cpp2Rust translates C++ to fully safe Rust automatically. It is a syntax-driven translator based on clang’s AST. Cpp2Rust’s algorithm is described in the paper Cpp2Rust: Automatic Translation of C++ to Safe Rust published at PLDI 2026. Cpp2Rust 可以自动将 C++ 代码转换为完全安全的 Rust 代码。它是一个基于 clang AST(抽象语法树)的语法驱动型翻译器。Cpp2Rust 的算法在发表于 PLDI 2026 的论文《Cpp2Rust: Automatic Translation of C++ to Safe Rust》中有详细描述。

Overview

概述

Cpp2Rust first parses the input C++ file(s) with clang and produces an AST. It then traverses the AST and emits Rust code as strings, inserting calls to the libcc2rs runtime library where needed (e.g., for raw pointer semantics). Finally, the Rust code is pretty-printed using rustfmt to a single .rs file. By default the reference counting model is used, which produces fully safe Rust. A generator of unsafe Rust is also available through the —model=unsafe command line argument for debugging and performance comparisons. Cpp2Rust 首先使用 clang 解析输入的 C++ 文件并生成 AST。随后,它会遍历 AST 并以字符串形式输出 Rust 代码,在必要时插入对 libcc2rs 运行时库的调用(例如处理原始指针语义)。最后,使用 rustfmt 对生成的 Rust 代码进行格式化,并输出到一个单独的 .rs 文件中。默认情况下,该工具使用引用计数模型,从而生成完全安全的 Rust 代码。此外,通过命令行参数 --model=unsafe,用户也可以选择生成不安全的 Rust 代码,以便进行调试和性能对比。

Runtime library (libcc2rs)

运行时库 (libcc2rs)

The generated code relies on a runtime library designed to simplify the translation process. C pointers are converted into the Ptr type provided by libcc2rs. Ptr models C pointer semantics, including null, arithmetic, and aliasing, while satisfying Rust’s borrow checker through checked run-time operations. 生成的代码依赖于一个旨在简化翻译过程的运行时库。C 指针会被转换为 libcc2rs 提供的 Ptr<T> 类型。Ptr<T> 模拟了 C 指针的语义(包括空指针、指针算术和别名),并通过运行时检查操作来满足 Rust 的借用检查器要求。

Requirements

系统要求

On Ubuntu, install the required dependencies with: 在 Ubuntu 上,请使用以下命令安装必要的依赖项:

sudo apt install libclang-22-dev clang++-22 ninja-build cmake
curl -LsSf https://astral.sh/ruff/install.sh | sh

Build

构建

mkdir build
cd build
cmake -GNinja ..
ninja
ninja check

Run

运行

Translate a single file: 翻译单个文件:

./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs

By default, the reference counting model is used (fully safe output). To generate unsafe Rust instead: 默认情况下使用引用计数模型(输出完全安全的代码)。若要生成不安全的 Rust 代码:

./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs --model=unsafe

Minimal example. Given hello.cpp: 最小示例。假设有 hello.cpp:

#include <cstdio>
int main() {
    printf("hello world\n");
    return 0;
}

Running ./build/cpp2rust/cpp2rust --file=hello.cpp -o=hello.rs produces: 运行 ./build/cpp2rust/cpp2rust --file=hello.cpp -o=hello.rs 后生成:

pub fn main() {
    std::process::exit(main_0());
}
fn main_0() -> i32 {
    println!("hello world");
    return 0;
}

Compile and run with: 编译并运行:

rustc hello.rs -L ../libcc2rs/target/debug
./hello

Translate a whole program

翻译整个程序

First generate a compile_commands.json for your project. With CMake this is one extra flag: 首先为你的项目生成 compile_commands.json。使用 CMake 时只需额外添加一个标志:

cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..

Then run: 然后运行:

./build/cpp2rust/cpp2rust --dir=<dir> -o <output>.rs

<dir> must be the directory that contains compile_commands.json. <dir> 必须是包含 compile_commands.json 的目录。

Test Suite

测试套件

# Run all tests
# 运行所有测试
ninja check

# Run only the unit tests
# 仅运行单元测试
ninja check-unit

# Run libcc2rs unit tests
# 运行 libcc2rs 单元测试
ninja check-libcc2rs

# Run libcc2rs-macros unit tests
# 运行 libcc2rs-macros 单元测试
ninja check-libcc2rs-macros

# Regenerate expected output for unit tests after intentional changes
# 在有意修改后重新生成单元测试的预期输出
REPLACE_EXPECTED=1 ninja check-unit