You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理Rust bindgen生成的std_vector类型

正确处理Rust中bindgen生成的C++ std::vector绑定的方法

直接手动构造std_vector结构体是错误的——C++ std::vector的内部结构依赖编译器实现,包含数据指针、容量指针、尾指针等关键成员,手动初始化_Mypair: (0)会导致空指针访问,触发运行时崩溃。以下是正确的解决方案:

核心思路:通过C++包装层管理std::vector

不要让Rust直接操作std_vector结构体,而是写一层简单的C++包装函数,负责std::vector<std::string>的创建、销毁、元素访问,再让Rust调用这些包装函数。

1. 编写C++包装代码

创建一个wrapper.cpp文件,封装原函数和vector的生命周期管理:

#include <vector>
#include <string>

// 原外部库函数声明
extern short REQ_MList(std::vector<std::string>* list);

extern "C" {
    // 创建空的std::vector<std::string>
    std::vector<std::string>* create_string_vector() {
        return new std::vector<std::string>();
    }

    // 销毁vector,释放内存
    void destroy_string_vector(std::vector<std::string>* vec) {
        delete vec;
    }

    // 获取vector的元素个数
    size_t string_vector_size(std::vector<std::string>* vec) {
        return vec->size();
    }

    // 获取指定索引的字符串的C风格指针(注意:指针有效期与vector绑定)
    const char* string_vector_get(std::vector<std::string>* vec, size_t index) {
        return vec->at(index).c_str();
    }

    // 暴露原函数给Rust
    short REQ_MList_wrapper(std::vector<std::string>* list) {
        return REQ_MList(list);
    }
}

2. 用bindgen生成Rust绑定

编译C++包装代码为静态/动态库后,使用bindgen生成对应的Rust绑定,生成的代码会包含以下函数(示例):

extern "C" {
    pub fn create_string_vector() -> *mut std_vector;
    pub fn destroy_string_vector(vec: *mut std_vector);
    pub fn string_vector_size(vec: *mut std_vector) -> usize;
    pub fn string_vector_get(vec: *mut std_vector, index: usize) -> *const ::std::os::raw::c_char;
    pub fn REQ_MList_wrapper(list: *mut std_vector) -> ::std::os::raw::c_short;
}

3. Rust侧调用示例

在Rust中通过包装函数安全操作C++ vector:

fn main() {
    unsafe {
        // 创建C++侧的vector
        let vec_ptr = create_string_vector();
        if vec_ptr.is_null() {
            panic!("Failed to allocate C++ vector");
        }

        // 调用原函数填充vector
        let result_code = REQ_MList_wrapper(vec_ptr);
        if result_code != 0 {
            eprintln!("REQ_MList failed with code: {}", result_code);
            destroy_string_vector(vec_ptr);
            return;
        }

        // 读取vector中的元素
        let elem_count = string_vector_size(vec_ptr);
        println!("Got {} elements:", elem_count);
        for i in 0..elem_count {
            let c_str_ptr = string_vector_get(vec_ptr, i);
            if !c_str_ptr.is_null() {
                match std::ffi::CStr::from_ptr(c_str_ptr).to_str() {
                    Ok(s) => println!("Element {}: {}", i, s),
                    Err(e) => println!("Element {}: Invalid string ({})", i, e),
                }
            }
        }

        // 必须销毁vector,避免内存泄漏
        destroy_string_vector(vec_ptr);
    }
}

关键注意事项

  • 所有裸指针操作必须放在unsafe块中,Rust无法保证C++内存的安全性。
  • 永远不要手动构造std_vector结构体,必须由C++侧的构造函数(create_string_vector)初始化。
  • 字符串指针的有效期与原vector绑定,不要在vector销毁后使用这些指针。

内容的提问来源于stack exchange,提问作者Udo Eisenbarth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 00:57:27