# cpp_vs_rust **Repository Path**: renfengyue/cpp_vs_rust ## Basic Information - **Project Name**: cpp_vs_rust - **Description**: No description available - **Primary Language**: C++ - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-16 - **Last Updated**: 2026-08-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # CPlusRust — C++ / Rust 双向 FFI 互调探索 一个 C++ 和 Rust **双向** FFI 混合编程的测试项目,覆盖从基础数据类型到复杂对象封装的 9 大场景,并附带性能对比基准测试。 ## 项目结构 ``` cplusrust/ ├── Cargo.toml # Rust 项目配置(lib + bin 双 target) ├── CMakeLists.txt # C++ 主导构建的编排入口 ├── build.rs # cmake 构建脚本(编译 C++ 静态库) ├── cpp_src/ # C++ 源代码 │ ├── CMakeLists.txt # cmake 构建(C++17) │ ├── cpp_ffi.h # extern "C" 接口头文件 (Rust FFI 入口) │ ├── cpp_ffi.cpp # FFI 实现,内部调用 C++ 类 │ ├── rust_exports.h # Rust #[no_mangle] 符号声明(供 C++ 主程序链接) │ ├── cpp_main.cpp # C++ 入口(C++ 主导建模式) │ ├── cpp_class.h # C++ 真实类 (Calculator, StringProcessor...) │ └── cpp_class.cpp # C++ 类实现 ├── src/ │ ├── lib.rs # Rust 库入口(staticlib 供 C++ 链接) │ ├── main.rs # Rust 入口 + 所有测试 + 性能基准 │ ├── cpp_bridge/mod.rs # C++ FFI 的 Rust 安全封装层 │ └── rust_exports/mod.rs # #[no_mangle] extern "C" 导出给 C++ 的函数 └── docs/ ``` ## 构建 & 运行 ### 前置条件 - **Rust** 工具链 (rustc, cargo) - **CMake** ≥ 3.10 - **MSVC** 编译器 (Windows) 或 **g++/clang++** (Linux/macOS) 支持 C++17 ### 编译运行(Rust 主导,默认) ```bash cargo run ``` `build.rs` 自动调用 cmake 编译 `cpp_src/` 为静态库,与 Rust 代码链接为单一可执行文件。 ```bash cargo run --release # Release 模式,C++ 侧启用 /O2 优化 ``` ### 编译运行(C++ 主导,对称验证) 将 Rust 编译为静态库,由 C++ `main()` 入口链接——验证双向 FFI 的对称完整性: ```bash mkdir build && cd build cmake .. && cmake --build . --config Debug .\Debug\cplusrust_cpp.exe ``` `build/` 是 C++ 主导路径的临时工作区,默认不纳入版本控制;需要时可以整目录删除后重新生成。 ## 测试场景 项目在 `main.rs` 中按顺序执行 12 类场景测试,共 37 个测试点: | # | 场景 | 说明 | |---|------|------| | 1 | **基础类型** | `int`、`double`、`bool` 跨语言双向传递 | | 2 | **复合类型** | `#[repr(C)]` struct 传值(Point、Line) | | 3 | **字符串** | 跨语言 String 传递,UTF-8 中文支持验证 | | 4 | **回调** | 跨语言函数指针注册与触发 | | 5 | **错误处理** | 返回码 + `get_last_error()` 模式(双方独立错误状态) | | 6 | **内存所有权** | "谁分配谁释放" 原则验证 | | 7 | **动态数组** | 原始指针 + 长度模式跨语言传递 | | 8 | **C++ 对象** | Opaque pointer + Rust `Drop` 自动释放 | | 9 | **反向互调** | Rust → C++ → Rust 双向调用链 | | 10 | **性能对比** | C++ vs Rust Fibonacci/素数筛/字符串拼接等 13 项基准 | | 11 | **嵌入式模式** | volatile packed 寄存器块、静态内存池、跨语言 volatile 读写 | | 12 | **嵌入式验证扩展** | userdata 回调、大结构体 SRet ABI、无堆深层错误链、CRC-32/CRC-16、packed 报文解析、锁竞争、空 FFI 调用开销、二进制尺寸报告 | ## 技术要点 ### 构建链 项目支持两种完全并行的构建方式: **Rust 主导(默认):** `Cargo → build.rs → cmake → MSVC/clang++ → cpp_bridge_static.lib → 链接 → 单一 .exe` **C++ 主导(对称验证):** `CMake → cargo build --lib → cplusrust.lib → 链接 cpp_main.cpp + cpp_bridge_static.lib → cplusrust_cpp.exe` 两条构建链目前**刻意使用独立的中间产物目录**: - Rust 主导路径把 C++ 静态库放在 Cargo 管理的 `target/.../build/.../out` 下。 - C++ 主导路径把 Rust 静态库放在 `build/cargo-target/` 下,并把整个 `build/` 目录视为一次性产物。 这样做的目的是让 `cargo run` 和 `cmake --build` 可以各自独立复现,不共享也不污染对方的中间结果。 ### FFI 安全设计 ``` Rust 侧 C++ 侧 ┌───────────────────────┐ ┌─────────────────────────┐ │ 安全封装层 │ │ extern "C" 包装层 │ │ - 关键路径参数校验 │ FFI │ - 状态码 + last error │ │ - Drop + 自动释放 │ ◄────► │ - 类型擦除(不透明指针) │ │ - &str/CString 校验 │ │ - 字符串失败返回 null │ │ - unsafe 隔离 │ │ - new/delete 配对 │ └───────────────────────┘ └─────────────────────────┘ ``` ### 关键约定 - **谁分配,谁释放** — C++ `new char[]` → C++ `delete[]`,Rust `Box::new` → Rust `drop` - **显式失败契约** — 返回数值/写入输出参数的 fallible API 使用 `0 = 成功 / 非 0 = 失败`,错误详情通过 `get_last_error()` / `rust_get_last_error()` 读取 - **字符串失败契约** — 返回 `char*` 的 fallible API 在失败时返回 `null`;仅在返回非空指针时由调用方按配对释放函数释放 - **不透明指针** — C++ `Calculator` / Rust `Counter` 通过 `*mut c_void` / `*mut CounterOpaque` 传递 - **`#[repr(C)]`** — Rust struct 布局与 C++ struct 对齐 - **嵌入式兼容** — `#[repr(C, packed)]` volatile register layout、`#[no_mangle]` 共享内存池 目前仓库已经为关键的 Rust 导出函数、字符串桥接和错误读取路径补上了空指针与内嵌 NUL 防护;仍然不应把任意原始指针当作有效句柄传入 FFI。 ### 依赖 - [`cmake` crate](https://crates.io/crates/cmake) — Rust build-dependency,编译 C++ 源码 ## 性能基准 项目对 **Fibonacci (n=40)**、**素数筛 (3M)**、**字符串拼接 (100k)** 三个场景做了 C++ 与 Rust 同等算法的对比测试,输出类似: ``` ┌─────────────────────────────────────────────┐ │ Fibonacci(n=40) x2 │ ├─────────────────────────────────────────────┤ │ C++ 0.523s │ Rust 0.612s │ │ 比率 C++/Rust = 0.855x │ └─────────────────────────────────────────────┘ ``` Rust 主入口和 C++ 主入口现在都使用相同口径:C++ 侧直接调用返回总耗时的 `bench_cpp_*_time`,Rust 侧则在入口中对纯 Rust 算法做等次数计时,避免一个入口测“benchmark 函数包装层”,另一个入口测“算法本身”。要直接比较两条入口打印出来的数字,仍然应当使用相同 profile 和相近编译选项。 可用于比较 MSVC / Clang / GCC 与 Rust 编译器在不同优化级别下的性能差异。 ## 使用场景 - 探索 C++/Rust **双向** FFI 技术栈 - 验证跨语言数据传递与内存安全方案 - 在既有 C++ 项目中逐步引入 Rust 模块(增量迁移) - 在既有 Rust 项目中封装高性能 C++ 库 - 对称验证:Rust 为主 / C++ 为主两种编译入口的 FFI 正确性 - 性能对比调优 ## 许可 MIT