我知道这可能是一个比较晦涩的要求,但有时候通过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);
如果您删除该行,则析构函数将永远不会被调用;我正在寻找一种方法将该内存块移回“安全”的 Rust 区域,并在块作用域结束时正确地进行收集。 编辑:我怀疑 swap() 是这样做的方法,但是正确执行它的确切语义对我来说仍然有点模糊。例如,在 https://gist.github.com/shadowmint/11361488 中,一个 ~Foo 泄漏了;忘记的 ~Foo 的析构函数被调用,但是我们泄漏了在 tmp 中创建的本地 ~Foo。 :/