首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将泛型对象传递给Rust,并在使用后返回C++进行销毁

将泛型对象传递给Rust,并在使用后返回C++进行销毁
EN

Stack Overflow用户
提问于 2020-06-24 07:28:17
回答 2查看 108关注 0票数 0

我想将缓冲区从C++发送到Rust,在Rust中读取它们,并在不再需要它们的时候在C++上销毁它们。

这是我用来接收的函数:

代码语言:javascript
复制
#[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]来分配这个数据。例如,我可能会使用一个字符串:

代码语言:javascript
复制
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中接收字符串/对象是一个空指针,但我不知道这是否可行。另外,第二个参数,析构函数,也需要是一个作用于泛型数据的函数,因为我可以传递一个不同于拥有数据的字符串的对象。

什么是一个优雅而安全的解决方案呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-24 11:25:45

在我看来,您至少有两种可能的途径。哪一种方法适用于您将在很大程度上取决于这些调用如何组合在一起。

最简单的做法是只考虑将从C++传递到rust的数据保留为C++所有。即期望smol_stack_smol_socket_send不破坏传递给它的缓冲区。这项工作落到了smol_stack_smol_socket_send的调用者身上。

rust代码可能如下所示:

代码语言:javascript
复制
#[no_mangle]
pub extern "C" fn simpler_function(
    data: *mut u8,
    len: usize,
) { .. }

然后,C++代码将如下所示:

代码语言:javascript
复制
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;
}

另一种方法是将回调传递给函数,以处理缓冲区的销毁

代码语言:javascript
复制
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++中,代码可能如下所示...

代码语言:javascript
复制
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集合中的某个位置,等等。

票数 3
EN

Stack Overflow用户

发布于 2020-06-24 22:18:16

如果您决定Rust需要取得对象的所有权,则可能需要编写一个实现Drop的包装器,以自动释放对象:

代码语言:javascript
复制
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)
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62545275

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档