pin_box_self_pointer_and_global_callback

#[derive(Debug)]
struct A {
    data: String,
}
impl A {
    fn show(&mut self) -> u64 {
        let p = self as *mut Self as u64;
        println!("in start p is {:x} {:?}", p, self);
        p
    }
}
static mut GLOBAL: Option<A> = None;

fn init() -> u64 {
    let p: u64 = {
        let mut a = A {
            data: "test".to_string(),
        };
        let p = a.show();
        unsafe { GLOBAL = Some(a) };
        p
    };
    p
}

pub fn main() {
    let a_pointer = init();
    unsafe { GLOBAL.as_mut().unwrap().show() };
    let a_ref: &mut A = unsafe { &mut *(a_pointer as *mut A) };
    a_ref.show();
}

这段代码会崩溃 因为 在init中我们将A构造出来了所得到的A的指针p在init函数后指向的就是非法的内存了. 在init 之后 A被存储在GLOBAL中其地址与被初始化时不同 解决的方法就是用Box

#[derive(Debug)]
struct A {
    data: String,
}

impl A {
    fn show(&mut self) -> u64 {
        let p = self as *mut Self as u64;
        println!("in start p is {:x} {:?}", p, self);
        p
    }
}
static mut GLOBAL: Option<Box<A>> = None;

fn init() -> u64 {
    let p: u64 = {
        let mut a = Box::new(A {
            data: "test".to_string(),
        });
        let p = a.show();
        unsafe { GLOBAL = Some(a) };
        p
    };
    p
}

pub fn main() {
    let a_pointer = init();
    unsafe { GLOBAL.as_mut().unwrap().show() };
    let a_ref: &mut A = unsafe { &mut *(a_pointer as *mut A) };
    a_ref.show();
}

实际上这样的代码就可以正常编译运行了 但是还有一个问题那就是show方法的定义 问题的本质在于我们希望在调用show方法时拿到的self是不变的 即A的内存地址在调用show之后就不能发生变化 那么就是Pin

#![feature(arbitrary_self_types)]
use core::pin::Pin;

#[derive(Debug)]
struct A {
    data: String,
}

impl A {
    fn show(self: Pin<&mut Self>) -> u64 {
        println!("in show self is {:?}", self);
        let p = self.get_mut() as *mut Self;
        println!("in start pointer is {:?}", p);
        p as u64
    }
}

static mut GLOBAL: Option<Pin<Box<A>>> = None;

fn init() -> u64 {
    let p: u64 = {
        let mut a = Pin::new(Box::new(A {
            data: "test".to_string(),
        }));
        let p = a.as_mut().show();
        unsafe { GLOBAL = Some(a) };
        p
    };
    p
}

pub fn main() {
    let a = init();
    let a= unsafe {&mut *(a as *mut A)};
    a.show();
    println!("a is {:?}",a);
}

这样好处就是我们无法在一个内存地址可能会发生变化的A上调用show 编译器会确保这一点