您能否以某种方式将不安全的指针转换为rust中的自有指针?

您能否以某种方式将不安全的指针转换为rust中的自有指针?,rust,Rust,我意识到这是一件很难理解的事情,但有时通过ffi在c库中存储一个值,然后从c回调一个rust函数会有所帮助 在这些情况下,我发现我希望拥有一个作为mut*c_void存储的自有指针 您可以使用此方法和forget()将值存储在C中,并且可以相对轻松地在另一端将其作为mut*T重新恢复,但是在这种情况下,能够移出不安全的指针并返回到“安全”的锈迹空间是很有用的 但是,编译器总是抱怨将引用移出指针(&p) 有没有一种特殊的方法,可以不安全地将a&T或*T转换为~T 这可能有点不清楚,所以这里有一个具

我意识到这是一件很难理解的事情,但有时通过ffi在c库中存储一个值,然后从c回调一个rust函数会有所帮助

在这些情况下,我发现我希望拥有一个作为mut*c_void存储的自有指针

您可以使用此方法和forget()将值存储在C中,并且可以相对轻松地在另一端将其作为mut*T重新恢复,但是在这种情况下,能够移出不安全的指针并返回到“安全”的锈迹空间是很有用的

但是,编译器总是抱怨将引用移出指针(&p)

有没有一种特殊的方法,可以不安全地将a&T或*T转换为~T

这可能有点不清楚,所以这里有一个具体的例子:

extern crate libc;

use libc::c_void;
use std::ops::Drop;
use std::intrinsics::forget;

struct Foo { x: int }

impl Drop for Foo {
  fn drop(&mut self) {
    println!("We discarded our foo thanks!");
  }
}

fn main() {
  let mut x = ~Foo { x: 10 };

  let mut y = & mut *x as * mut Foo;
  println!("Address Y: {:x}", y as uint);

  let mut z = y as * mut c_void;
  println!("Address Z: {:x}", z as uint);

  // Forget x so we don't worry about it
  unsafe { forget(x); }

  // This would normally happen inside the ffi callback where 
  // the ffi code discards the void * it was holding and returns it.
  unsafe {
    let mut res_z = z as * mut Foo;
    println!("Ressurected Z: {:x}", z as uint);

    let mut res_y = & mut (*res_z);
    println!("Ressurected Y: {:x}", y as uint);

    let mut res_x:~Foo = ~(*res_y);
  }
}
最后一行无法编译,因为:

test.rs:34:28: 34:34 error: cannot move out of dereference of `&mut`-pointer
test.rs:34     let mut res_x:~Foo = ~(*res_y);
如果删除该行,则永远不会调用析构函数;我正在寻找一种方法,将内存块移回“安全”锈蚀区,并在块作用域结束时正确收集它


编辑:我怀疑swap()是实现这一点的方法,但正确地执行而不泄漏的确切语义对我来说仍然有点模糊。例如在~Foo泄漏中;为忘记的~Foo调用析构函数,但我们泄漏了在tmp中创建的本地~Foo:/

语法正确吗?如果我没有错的话,这条线应该如下所示

let mut res_x:~Foo = (*res_y);

我是一个生锈的新手,我只是按照这个[链接]:

你的错误发生了,因为
~
是装箱的操作符,而不是指针。您不能将一个拥有的指针“带”到某个对象,因为创建一个拥有的指针总是意味着在堆上进行分配。因此,您的错误-
~
尝试将值移出
&mut
,这是不允许的

我相信,对于这种真正不安全的事情,您需要
cast::transmute()


您的代码经过此修改后运行良好,并打印出
我们放弃了我们的foo谢谢。但是,您确实应该小心使用
cast::transmute()
,因为它完全不进行任何检查(转换类型的内存大小除外),并且允许您将所有内容强制转换为所有内容。

否则,我认为您需要再编写一个函数来调用resu y的析构函数,该函数可以在外部访问。在这种情况下,resu y是&mut T T,我想把它“提升”成一个~T.*resuy,实际上是一个T,但我想把它转换成一个自有指针。
use std::cast;

// ...

let mut res_x: ~Foo = cast::transmute(res_y);