我想将缓冲区从C++发送到Rust,在Rust中读取它们,并在不再需要它们的时候在C++上销毁它们。
这是我用来接收的函数:
#[no_mangle]
pub extern "C" fn smol_stack_smol_socket_send(
smol_stack: &mut SmolStackType,
socket_handle_key: usize,
data: *mut u8,
len: usize,
endpoint: CIpEndpoint,
) -> u8 {我想接收一个指向uint8_t数据的指针,但是我也不认为我需要自己使用new uint8_t[size]来分配这个数据。例如,我可能会使用一个字符串:
std::string* s = new std::string("hello");然后简单地将s.c_str()作为uint8_t*传递给Rust。我不能简单地调用delete[] s.c_str(),我需要删除C++端的s字符串。因此,我正在考虑向我的函数smol_stack_smol_socket_send添加另外两个参数。一个是指向拥有uint8_t缓冲区的对象(在本例中是字符串,但也可以是另一个)的指针,另一个是指向接收该对象并进行析构的函数的指针。
我认为在Rust中接收字符串/对象是一个空指针,但我不知道这是否可行。另外,第二个参数,析构函数,也需要是一个作用于泛型数据的函数,因为我可以传递一个不同于拥有数据的字符串的对象。
什么是一个优雅而安全的解决方案呢?
发布于 2020-06-24 11:25:45
在我看来,您至少有两种可能的途径。哪一种方法适用于您将在很大程度上取决于这些调用如何组合在一起。
最简单的做法是只考虑将从C++传递到rust的数据保留为C++所有。即期望smol_stack_smol_socket_send不破坏传递给它的缓冲区。这项工作落到了smol_stack_smol_socket_send的调用者身上。
rust代码可能如下所示:
#[no_mangle]
pub extern "C" fn simpler_function(
data: *mut u8,
len: usize,
) { .. }然后,C++代码将如下所示:
void with_string() {
std::string buffer("Hello World");
simpler_function(buffer.c_str(), buffer.length());
// C++ destroys the string here.
}
void with_newed_buffer() {
char* buffer=new char[10];
buffer[0]='A';
buffer[1]=0;
simpler_function(buffer, 2);
delete [] buffer;
}另一种方法是将回调传递给函数,以处理缓冲区的销毁
type Destructor = extern "C" fn(*mut c_void);
#[no_mangle]
pub extern "C" fn core_function(
data: *mut u8,
len: usize,
calback_data: *mut c_void
destructor: Destructor
) {
..
// We're done with the data - destroy it
destructor(callback_data);
}现在,在C++中,代码可能如下所示...
void delete_buffer(void* buffer) {
delete [] (char*)buffer;
}
void with_newed_buffer() {
char* buffer=new char[10];
buffer[0]='A';
buffer[1]=0;
simpler_function(buffer, 2, buffer, delete_buffer);
}我想你应该总是更喜欢第一种方法。唯一不起作用的情况是rust需要取得C++对象的所有权(并因此控制其生命周期)。通常,这意味着将其存储在rust集合中的某个位置,等等。
发布于 2020-06-24 22:18:16
如果您决定Rust需要取得对象的所有权,则可能需要编写一个实现Drop的包装器,以自动释放对象:
struct Whatever {
data: *mut u8,
len: usize,
object: *mut c_void,
destructor: extern "C" fn(*mut c_void),
}
impl Drop for Whatever {
fn drop(&mut self) {
self.destructor(self.object)
}
}https://stackoverflow.com/questions/62545275
复制相似问题