我从Rust返回一个结构体给C代码。我不知道这是否是一种好的做法,但它确实可以重新构建结构体并在没有泄漏的情况下释放内存。
#[repr(C)]
pub struct s {
// ...
}
#[repr(C)]
#[allow(clippy::box_vec)]
pub struct s_arr {
arr: *const s,
n: i8,
vec: Box<Vec<s>>,
}
/// Frees memory that was returned to C code
pub unsafe extern "C" fn free_s_arr(a: *mut s_arr) {
Box::from_raw(s_arr);
}
/// Generates an array for the C code
pub unsafe extern "C" fn gen_s_arr() -> *mut s_arr {
let many_s: Vec<s> = Vec::new();
// ... logic here
Box::into_raw(Box::new(s_arr {
arr: many_s.as_mut_ptr(),
n: many_s.len() as i8,
vec: many_s,
}))
}
目前C头文件是手写的,但我想尝试使用cbindgen。 s_arr
的手动C定义如下:
struct s_arr {
struct s *arr;
int8_t n;
void *_;
};
cbindgen 为 s_arr
生成以下内容:
typedef struct Box_Vec_s Box_Vec_s;
typedef struct s_arr {
const s *arr;
int8_t n;
Box_Vec_s vec;
} s_arr;
这不起作用,因为
struct Box_Vec_s
未定义。理想情况下,我只想覆盖为vec
生成的cbindgen类型,使其成为void *
,因为它不需要任何代码更改,也没有额外的测试,但我可以接受其他建议。我已经查看了cbindgen文档,尽管没有查看示例,但仍然找不到任何内容。
std::mem::forget(many_s);
,这保证不会泄漏吗?我期望Vec中唯一分配在堆上的结构成员是动态数组,但也许将来还有另一个Vec成员在堆上。我只是相信stdlib维护者会保持Vec这种方式吗?这更多是一个学术问题而不是实际问题 - 您的解决方案完全符合我的需求。 - MrTheFoolish