Rust C++互操作库autocxx-macro的使用:实现安全高效的Rust与C++代码自动绑定

Rust C++互操作库autocxx-macro的使用:实现安全高效的Rust与C++代码自动绑定

安装

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

cargo add autocxx-macro

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

autocxx-macro = "0.30.0"

元数据

  • 版本: 0.30.0
  • 发布时间: 5个月前
  • Rust版本: 2021 edition
  • 许可证: MIT OR Apache-2.0
  • 大小: 4.25 KiB

示例代码

下面是一个使用autocxx-macro实现Rust与C++互操作的完整示例:

// 首先,确保在Cargo.toml中添加了autocxx-macro依赖
// autocxx-macro = "0.30.0"

use autocxx_macro::autocxx;

// 假设我们有一个C++头文件example.h
// 内容如下:
/*
#pragma once

#include <string>

class Example {
public:
    Example();
    ~Example();
    
    std::string say_hello(const std::string& name) const;
};
*/

// 使用autocxx宏绑定C++类
autocxx! {
    #include "example.h"
    
    // 生成Rust绑定
    generate!("Example")
}

// 现在可以在Rust中使用C++的Example类
fn main() {
    // 创建C++对象
    let example = ffi::Example::new().within_unique_ptr();
    
    // 调用C++方法
    let name = "Rust".to_string();
    let greeting = example.say_hello(&name);
    
    println!("C++ says: {}", greeting);
}

完整示例demo

// Cargo.toml需要包含以下依赖
// autocxx-macro = "0.30.0"
// autocxx-build = "0.30.0"

// build.rs需要包含以下内容
/*
fn main() {
    let path = std::path::PathBuf::from("src"); // 头文件所在目录
    autocxx_build::Builder::new("src/lib.rs", &[&path])
        .build()
        .unwrap()
        .compile("autocxx-demo");
}
*/

use autocxx_macro::autocxx;

// 假设我们有一个C++头文件math_utils.h
/*
#pragma once

namespace math {
    class Calculator {
    public:
        Calculator();
        ~Calculator();
        
        int add(int a, int b);
        double multiply(double a, double b);
    };
}
*/

// 使用autocxx宏绑定C++类
autocxx! {
    #include "math_utils.h"
    
    // 生成Rust绑定
    generate_pod!("math::Calculator")
}

fn main() {
    // 创建C++计算器对象
    let calculator = ffi::math::Calculator::new().within_unique_ptr();
    
    // 调用C++加法方法
    let sum = calculator.add(5, 3);
    println!("5 + 3 = {}", sum);
    
    // 调用C++乘法方法
    let product = calculator.multiply(4.2, 2.5);
    println!("4.2 * 2.5 = {}", product);
}

实现说明

  1. autocxx!宏用于解析C++头文件并生成相应的Rust绑定
  2. generate!generate_pod!宏指定要绑定的C++类或函数
  3. 生成的C++对象通常包装在智能指针中(如unique_ptr)以确保内存安全
  4. 基本类型和复杂类型会自动进行Rust和C++之间的转换
  5. 需要配合build.rs构建脚本来自动生成绑定代码

分类

  • API绑定
  • FFI(外部函数接口)

1 回复

Rust C++互操作库autocxx-macro的使用:实现安全高效的Rust与C++代码自动绑定

介绍

autocxx-macro 是一个用于 Rust 和 C++ 互操作的库,它通过自动生成绑定代码来简化 Rust 与 C++ 的交互过程。该库旨在提供安全、高效的绑定方式,同时减少手动编写 FFI (Foreign Function Interface) 代码的工作量。

主要特点:

  • 自动生成安全的 Rust 与 C++ 绑定
  • 减少手动编写不安全代码的需求
  • 支持 C++ 类的包装和使用
  • 提供类型安全的接口
  • 基于 cxx 库构建,但提供了更高层次的抽象

安装

在 Cargo.toml 中添加依赖:

[dependencies]
autocxx = "0.22"

完整示例demo

下面是一个完整的示例项目,展示如何使用autocxx实现Rust与C++的互操作:

  1. 首先创建项目结构:
autocxx_demo/
├── Cargo.toml
├── build.rs
├── src/
│   ├── lib.rs
│   ├── calculator.h
│   └── main.rs
  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 内容:
// 构建脚本,指定要绑定的C++头文件
fn main() {
    let path = std::path::PathBuf::from("src"); // 头文件所在目录
    autocxx_build::Builder::new("src/lib.rs", &[&path])
        .build()
        .unwrap()
        .compile("autocxx-demo");
    println!("cargo:rerun-if-changed=src/lib.rs");
}
  1. src/calculator.h 内容:
// C++计算器类定义
class Calculator {
public:
    Calculator();
    int add(int a, int b);
    double sqrt(double value);
};
  1. src/lib.rs 内容:
use autocxx::include_cpp;

// 包含C++头文件并生成绑定
include_cpp! {
    #include "calculator.h"
    safety!(unsafe_ffi)  // 明确标记FFI操作是不安全的
    generate!("Calculator")  // 生成Calculator类的绑定
}

pub struct RustCalculator;

impl RustCalculator {
    // 包装C++计算器的Rust接口
    pub fn add(a: i32, b: i32) -> i32 {
        let calc = ffi::Calculator::new().within_unique_ptr();
        calc.add(a, b)
    }
    
    pub fn sqrt(value: f64) -> f64 {
        let calc = ffi::Calculator::new().within_unique_ptr();
        calc.sqrt(value)
    }
}
  1. src/main.rs 内容:
use autocxx_demo::RustCalculator;

fn main() {
    println!("5 + 3 = {}", RustCalculator::add(5, 3));
    println!("sqrt(16.0) = {}", RustCalculator::sqrt(16.0));
}
  1. 实现C++代码(需要单独编译为库):
// calculator.cpp
#include "calculator.h"

Calculator::Calculator() = default;

int Calculator::add(int a, int b) {
    return a + b;
}

double Calculator::sqrt(double value) {
    if(value < 0) return -1;
    return std::sqrt(value);
}

构建和运行说明

  1. 首先编译C++代码为静态库:
g++ -c calculator.cpp -o calculator.o
ar rcs libcalculator.a calculator.o
  1. 然后构建并运行Rust项目:
LIBRARY_PATH=$PWD cargo run

注意事项

  1. 确保C++库能够被链接器找到
  2. 在build.rs中正确指定头文件路径
  3. 所有通过FFI传递的数据类型必须兼容
  4. 需要正确处理内存管理和对象生命周期

这个完整示例展示了如何使用autocxx将C++类包装为Rust接口,并通过Rust调用C++功能。这种方式可以在保留现有C++代码的同时,逐步将项目迁移到Rust。

回到顶部