你能不能以某种方式将不安全的指针转换为生锈的指针?

时间:2014-04-28 02:56:23

标签: rust

我意识到这是一件想要做的事情,但有时候能够通过ffi在ac库中存储一个值,然后从c回调一个rust函数有点帮助

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

您可以使用此方法将存储在 C中的值与forget()一起存储,并且您可以相对轻松地将其作为mut * T复活到另一端,但它很有用能够移出不安全的指针,然后回到“安全”状态。在这种情况下生锈空间。

然而,编译器总是会抱怨将参考文件移出&指针。

是否有一种特殊的方法,将& 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()是这样做的方法,但是在没有泄漏的情况下正确执行它的确切语义对我来说仍然有点模糊。例如在https://gist.github.com/shadowmint/11361488 a~Foo泄漏;对于被遗忘的~Foo调用析构函数,但是我们泄漏了在tmp中创建的本地~Foo。 :/

2 个答案:

答案 0 :(得分:2)

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

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

use std::cast;

// ...

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

使用此修改的代码工作正常,并打印We discarded our foo thanks!。但是,你应该小心 小心cast::transmute(),因为它完全没有检查(转换类型的内存大小除外),并且允许你将所有内容都转换为所有内容。

答案 1 :(得分:0)

语法是否正确?如果我没错的话,该行应该如下所示。

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

我是一个生锈的新手,我只是按照这个[链接]:http://cmr.github.io/blog/2013/08/13/rust-by-concept/