如何处理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
相关产品推荐
相关产品推荐

