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);
}
实现说明
autocxx!
宏用于解析C++头文件并生成相应的Rust绑定generate!
或generate_pod!
宏指定要绑定的C++类或函数- 生成的C++对象通常包装在智能指针中(如
unique_ptr
)以确保内存安全 - 基本类型和复杂类型会自动进行Rust和C++之间的转换
- 需要配合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++的互操作:
- 首先创建项目结构:
autocxx_demo/
├── Cargo.toml
├── build.rs
├── src/
│ ├── lib.rs
│ ├── calculator.h
│ └── main.rs
- Cargo.toml 内容:
[package]
name = "autocxx-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
autocxx = "0.22"
[build-dependencies]
autocxx-build = "0.22"
- 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");
}
- src/calculator.h 内容:
// C++计算器类定义
class Calculator {
public:
Calculator();
int add(int a, int b);
double sqrt(double value);
};
- 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)
}
}
- src/main.rs 内容:
use autocxx_demo::RustCalculator;
fn main() {
println!("5 + 3 = {}", RustCalculator::add(5, 3));
println!("sqrt(16.0) = {}", RustCalculator::sqrt(16.0));
}
- 实现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);
}
构建和运行说明
- 首先编译C++代码为静态库:
g++ -c calculator.cpp -o calculator.o
ar rcs libcalculator.a calculator.o
- 然后构建并运行Rust项目:
LIBRARY_PATH=$PWD cargo run
注意事项
- 确保C++库能够被链接器找到
- 在build.rs中正确指定头文件路径
- 所有通过FFI传递的数据类型必须兼容
- 需要正确处理内存管理和对象生命周期
这个完整示例展示了如何使用autocxx将C++类包装为Rust接口,并通过Rust调用C++功能。这种方式可以在保留现有C++代码的同时,逐步将项目迁移到Rust。