如何在Rust中调用C++库

我想在Rust项目中使用一个现有的C++库,但不太清楚具体该如何操作。请问应该如何正确地在Rust中调用C++库?需要特别注意哪些兼容性问题?是否有推荐的绑定生成工具或最佳实践?另外,在跨语言调用时,内存管理和类型转换方面有什么需要特别注意的地方吗?

2 回复

使用Rust调用C++库,步骤如下:

  1. extern "C"包装C++函数,消除名称修饰
  2. 创建头文件声明函数
  3. 在Rust中使用#[link]extern声明外部函数
  4. 用build.rs脚本编译C++代码并链接

注意处理类型转换和内存安全。可用cbindgen自动生成FFI绑定。


在Rust中调用C++库,可以通过Rust的FFI(Foreign Function Interface)功能实现。主要步骤包括:

  1. 创建C接口:由于Rust无法直接调用C++,需要为C++库创建C风格的接口包装器。

  2. 使用extern "C":在C++中,用extern "C"声明函数,避免名称修饰(name mangling)。

  3. Rust声明外部函数:在Rust中使用extern "C"块声明C函数。

  4. 链接库:在Rust中指定链接C++库。

示例步骤

1. C++库代码(例如mylib.cpp

#include <iostream>

extern "C" {
    void greet() {
        std::cout << "Hello from C++!" << std::endl;
    }
    
    int add(int a, int b) {
        return a + b;
    }
}

编译为共享库:

g++ -shared -fPIC -o libmylib.so mylib.cpp

2. Rust代码(src/main.rs

// 声明外部C函数
extern "C" {
    fn greet();
    fn add(a: i32, b: i32) -> i32;
}

fn main() {
    unsafe {
        greet(); // 调用C++函数
        let result = add(3, 4);
        println!("3 + 4 = {}", result);
    }
}

3. 配置链接(在Cargo.toml或构建脚本)

  • 方法1:在build.rs中(推荐):
fn main() {
    println!("cargo:rustc-link-search=native=/path/to/library");
    println!("cargo:rustc-link-lib=dylib=mylib");
}
  • 方法2:直接使用#[link]属性(在Rust代码中):
#[link(name = "mylib", kind = "dylib")]
extern "C" {
    // 函数声明
}

注意事项

  • 内存安全:Rust调用C++代码必须在unsafe块中进行。
  • 类型转换:确保Rust和C++类型匹配(如i32对应int)。
  • 异常处理:C++异常不能直接传递给Rust,需在C++侧捕获并转换为错误码。
  • 构建工具:可使用cccmakecrate自动化编译C++代码。

对于复杂项目,推荐使用bindgen自动生成Rust绑定,或cxx crate简化互操作。

回到顶部