你能以某种方式将一个不安全的指针转换为rust中的一个拥有的指针吗



我意识到这是一件不太清楚的事情,但有时通过ffi将值存储在c库中,然后从c.回调rust函数会有所帮助

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

您可以将值与forget()一起使用此方法存储在C中,并且您可以相对容易地在另一端将其恢复为mut*T,但在这种情况下,能够移出不安全的指针并返回到"安全"的rust空间是很有用的。

然而,编译器总是抱怨将引用从&指针。

有没有一种特殊的方法,不安全地转换一个&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);

如果删除该行,则永远不会调用析构函数;我正在寻找一种方法,将内存块移回"安全"锈蚀区,并在块作用域结束时正确收集。

edit:我怀疑swap()是实现这一点的方法,但在不泄漏的情况下正确执行的确切语义对我来说仍然有点模糊https://gist.github.com/shadowmint/11361488a~Foo泄漏;析构函数是为被遗忘的~Foo调用的,但我们却泄露了在tmp中创建的本地~Foo。:/

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

我相信,对于这种真正不安全的东西,你需要cast::transmute():

use std::cast;
// ...
let mut res_x: ~Foo = cast::transmute(res_y);

经过此修改后,您的代码运行良好,并且会打印We discarded our foo thanks!。然而,您应该非常小心cast::transmute(),因为它完全不进行检查(除了转换类型的内存大小),并允许您将所有内容强制转换为所有内容。

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

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

我是一个新手,我刚刚关注了这个[链接]:http://cmr.github.io/blog/2013/08/13/rust-by-concept/

最新更新