Rust C++互操作库autocxx-parser的使用:实现Rust与C++代码无缝桥接的解析器工具

Rust C++互操作库autocxx-parser的使用:实现Rust与C++代码无缝桥接的解析器工具

这个crate是autocxx的一个组件。

安装

在您的项目目录中运行以下Cargo命令:

cargo add autocxx-parser

或者在您的Cargo.toml中添加以下行:

autocxx-parser = "0.30.0"

示例代码

以下是一个完整的示例,展示如何使用autocxx-parser来实现Rust与C++的互操作:

// 首先,在build.rs中使用autocxx-build
autocxx_build::Builder::new("src/ffi.rs", &["src"])
    .build()
    .unwrap()
    .compile("autocxx-demo");

// 然后在src/ffi.rs中定义C++接口
autocxx::include_cpp! {
    #include "my_header.h"
    generate!("MyCppClass")
    safety!(unsafe)
}

// 在Rust代码中使用生成的绑定
use autocxx::prelude::*;

fn main() {
    let cpp_obj = ffi::MyCppClass::new().within_unique_ptr();
    let result = cpp_obj.as_ref().unwrap().some_method();
    println!("Result from C++: {}", result);
}

对应的C++头文件my_header.h可能如下:

// my_header.h
class MyCppClass {
public:
    MyCppClass();
    int some_method();
};

完整示例

下面是一个更完整的项目结构示例:

  1. 首先创建项目结构:
cargo new autocxx_example
cd autocxx_example
  1. 编辑Cargo.toml添加依赖:
[package]
name = "autocxx_example"
version = "0.1.0"
edition = "2021"

[dependencies]
autocxx = "0.30.0"

[build-dependencies]
autocxx-build = "0.30.0"
  1. 创建build.rs构建脚本:
// build.rs
fn main() {
    autocxx_build::Builder::new("src/ffi.rs", &["src"])
        .build()
        .unwrap()
        .compile("autocxx-example");
    println!("cargo:rerun-if-changed=src/ffi.rs");
    println!("cargo:rerun-if-changed=src/my_header.h");
}
  1. 创建C++头文件src/my_header.h:
// src/my_header.h
class MyCppClass {
public:
    MyCppClass();
    int some_method() { return 42; }
};
  1. 创建FFI接口定义src/ffi.rs:
// src/ffi.rs
autocxx::include_cpp! {
    #include "my_header.h"
    generate!("MyCppClass")
    safety!(unsafe)
}
  1. 修改主程序src/main.rs:
// src/main.rs
mod ffi;

use autocxx::prelude::*;

fn main() {
    // 创建C++对象包装在Rust的UniquePtr中
    let cpp_obj = ffi::MyCppClass::new().within_unique_ptr();
    
    // 调用C++方法
    let result = cpp_obj.as_ref().unwrap().some_method();
    
    // 打印结果
    println!("The answer from C++ is: {}", result);
}

元数据

  • 版本:0.30.0
  • 发布日期:5个月前
  • 版本:2021 edition
  • 许可证:MIT OR Apache-2.0
  • 大小:12.7 KiB

类别

  • API bindings
  • FFI (开发工具)

所有者

  • Adrian Taylor
  • pgrace-google

请注意,autocxx-parser是autocxx生态系统的一部分,主要用于解析C++代码并生成Rust绑定。完整的互操作解决方案需要使用autocxx主库。


1 回复

Rust C++互操作库autocxx-parser的使用指南

概述

autocxx-parser 是一个用于实现 Rust 与 C++ 代码无缝桥接的解析器工具,它是 autocxx 项目的一部分。该工具允许开发者安全高效地在 Rust 中调用 C++ 代码,同时避免手动编写不安全的 FFI 绑定。

主要特性

  • 自动解析 C++ 头文件生成 Rust 绑定
  • 类型安全的内存管理
  • 零成本抽象
  • 支持大多数 C++ 特性
  • 与 Cargo 构建系统集成

安装方法

首先在 Cargo.toml 中添加依赖:

[dependencies]
autocxx = "0.22"

还需要安装一些系统依赖:

  • Python 3
  • Clang
  • C++ 构建工具链

基本使用方法

  1. 创建一个 build.rs 构建脚本:
fn main() {
    let path = std.path::PathBuf::from("src"); // 头文件所在目录
    autocxx_build::Builder::new("src/lib.rs", &[&path])
        .build()
        .unwrap()
        .compile("autocxx-demo"); // 输出静态库名称
}
  1. lib.rs 中定义要绑定的 C++ 头文件:
use autocxx::include_cpp;

include_cpp! {
    #include "my_header.h"
    safety!(unsafe_ffi)
    generate!("MyCppClass")
}

示例:调用 C++ 类

假设有一个 C++ 头文件 my_header.h:

class MyCppClass {
public:
    MyCppClass(int value);
    int get_value() const;
    void set_value(int value);
private:
    int value_;
};

在 Rust 中可以这样使用:

use autocxx::include_cpp;

include_cpp! {
    #include "my_header.h"
    safety!(unsafe_ffi)
    generate!("MyCppClass")
}

fn main() {
    let mut obj = ffi::MyCppClass::new(42).within_unique_ptr();
    println!("Initial value: {}", obj.get_value());
    obj.pin_mut().set_value(100);
    println!("New value: {}", obj.get_value());
}

完整示例demo

以下是一个完整的 Rust 与 C++ 互操作示例:

  1. 首先创建 C++ 头文件 src/my_header.h:
// 简单的C++类示例
class MyCppClass {
public:
    MyCppClass(int value);
    int get_value() const;
    void set_value(int value);
private:
    int value_;
};
  1. 创建 C++ 实现文件 src/my_header.cpp:
#include "my_header.h"

MyCppClass::MyCppClass(int value) : value_(value) {}

int MyCppClass::get_value() const {
    return value_;
}

void MyCppClass::set_value(int value) {
    value_ = value;
}
  1. 创建 Rust 项目结构:
my_project/
├── Cargo.toml
├── build.rs
├── src/
│   ├── lib.rs
│   ├── main.rs
│   ├── my_header.h
│   └── my_header.cpp
  1. 编辑 Cargo.toml:
[package]
name = "autocxx-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
autocxx = "0.22"

[build-dependencies]
autocxx-build = "0.22"
  1. 编辑 build.rs:
fn main() {
    // 编译C++代码
    cc::Build::new()
        .cpp(true)
        .file("src/my_header.cpp")
        .compile("my_header");

    // 生成Rust绑定
    let path = std::path::PathBuf::from("src");
    autocxx_build::Builder::new("src/lib.rs", &[&path])
        .build()
        .unwrap()
        .compile("autocxx-demo");
}
  1. 编辑 src/lib.rs:
use autocxx::include_cpp;

include_cpp! {
    #include "my_header.h"
    safety!(unsafe_ffi)
    generate!("MyCppClass")
}
  1. 编辑 src/main.rs:
mod ffi; // 导入生成的绑定

fn main() {
    // 创建C++对象
    let mut obj = ffi::MyCppClass::new(42).within_unique_ptr();
    
    // 调用C++方法
    println!("Initial value: {}", obj.get_value());
    
    // 修改值
    obj.pin_mut().set_value(100);
    println!("New value: {}", obj.get_value());
}

高级用法

处理继承

include_cpp! {
    #include "base.h"
    #include "derived.h"
    safety!(unsafe_ffi)
    generate!("BaseClass")
    generate!("DerivedClass")
    subclass!("BaseClass", "DerivedClass")
}

处理模板

include_cpp! {
    #include "vector"
    safety!(unsafe_ffi)
    generate!("std::vector<int>")
    generate!("std::vector<float>")
}

注意事项

  1. 需要处理 C++ 异常,autocxx 会将它们转换为 Rust 的 Result 类型
  2. 某些高级 C++ 特性可能不完全支持
  3. 性能关键代码可能需要特殊处理
  4. 内存管理遵循 Rust 的所有权规则

调试技巧

  1. 使用 autocxx_gen 工具预览生成的绑定代码:
cargo install autocxx-gen
autocxx-gen src/lib.rs --generate-exact-code
  1. 检查构建过程中生成的临时文件以排查问题

autocxx-parser 为 Rust 与 C++ 互操作提供了强大而安全的解决方案,大大简化了两种语言间的桥接工作。

回到顶部