< 返回版块

‘static 发表于 2020-09-19 21:55

pub trait Interface {
    fn print_info(&mut self);
}
struct Holder<'a>(&'a mut (Interface + 'a));
#[derive(Debug)]
struct User {
    name: String,
    age: u32,
}

impl Interface for User {
    fn print_info(&mut self) {
        println!("{:#?}", self);
        self.age += 1;
    }
}
//供外部传入实现
pub fn set_interface(i: &mut Interface) {
    let h = Holder(i);
    unsafe {
        GLOBAL_INTERFACE = std::mem::transmute(&h);
    }
}
//全局trait
static mut GLOBAL_INTERFACE: *mut Holder<'static> = 0 as *mut _;
fn main() {
    let mut u1 = User {
        name: "stack overflow 666".to_string(),
        age: 18,
    };
    set_interface(&mut u1);
    unsafe {
        (*GLOBAL_INTERFACE).0.print_info(); //第一次没问题
        println!("-------------");
        (*GLOBAL_INTERFACE).0.print_info(); //第二次直接退出exit code: 0xc0000005, STATUS_ACCESS_VIOLATION
    }
}

评论区

写评论
作者 ‘static 2020-09-20 20:19

这个完美,思路清晰,满足要求,灵活,大佬666。刚学rust生命周期、指针之类的,感觉悟了又会被编译器吊打。感谢!

👇
93996817:

use once_cell::sync::OnceCell;
use std::{sync::Arc, sync::Mutex};

pub trait ILogger: Send + Sync + 'static {
   fn print(&mut self);
}
#[derive(Debug)]
pub struct Logger {
   pub age: i32,
}

pub struct Holder(Box<dyn ILogger>);

static INSTANCE: OnceCell<Arc<Mutex<Holder>>> = OnceCell::new();
pub struct Global{}
impl Global {
   pub fn global() -> &'static Arc<Mutex<Holder>> {
       INSTANCE.get().unwrap()
   }
}

impl ILogger for Logger {
   fn print(&mut self) {
       self.age += 1;
       println!("{:?}", self);
   }
}

#[derive(Debug)]
struct Logger2 {
   score: i32,
}

impl ILogger for Logger2 {
   fn print(&mut self) {
       self.score += 1;
       println!("{:?}", self);
   }
}

fn main() {
   let logger1 = Logger { age: 1 };
   let holder1 = Holder(box logger1);
   let set_result = INSTANCE.set(Arc::new(Mutex::new(holder1)));
   let mut data = Global::global().lock().unwrap();
   data.0.print();
   data.0.print();
   let logger2 = Logger2 { score: 2 };
   data.0 = box logger2;
   data.0.print();
   data.0.print();
}
PS Z:\rust\study\test001> cargo run 
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target\debug\test001.exe`
Logger { age: 2 }
Logger { age: 3 }   
Logger2 { score: 3 }
Logger2 { score: 4 }
PS Z:\rust\study\test001> 

作者 ‘static 2020-09-20 20:02
Extending a lifetime, or shortening an invariant lifetime. This is advanced, very unsafe Rust!

struct R<'a>(&'a i32);
unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
    std::mem::transmute::<R<'b>, R<'static>>(r)
}

被逆天改命了

👇
liyiheng: 有个疑问, h 不是在 set_interface 里面 drop 么? 为什么第一次打印的时候没出错呢

liyiheng 2020-09-20 19:27

有个疑问, h 不是在 set_interface 里面 drop 么? 为什么第一次打印的时候没出错呢

93996817 2020-09-20 17:14
use once_cell::sync::OnceCell;
use std::{sync::Arc, sync::Mutex};

pub trait ILogger: Send + Sync + 'static {
    fn print(&mut self);
}
#[derive(Debug)]
pub struct Logger {
    pub age: i32,
}

pub struct Holder(Box<dyn ILogger>);

static INSTANCE: OnceCell<Arc<Mutex<Holder>>> = OnceCell::new();
pub struct Global{}
impl Global {
    pub fn global() -> &'static Arc<Mutex<Holder>> {
        INSTANCE.get().unwrap()
    }
}

impl ILogger for Logger {
    fn print(&mut self) {
        self.age += 1;
        println!("{:?}", self);
    }
}

#[derive(Debug)]
struct Logger2 {
    score: i32,
}

impl ILogger for Logger2 {
    fn print(&mut self) {
        self.score += 1;
        println!("{:?}", self);
    }
}

fn main() {
    let logger1 = Logger { age: 1 };
    let holder1 = Holder(box logger1);
    let set_result = INSTANCE.set(Arc::new(Mutex::new(holder1)));
    let mut data = Global::global().lock().unwrap();
    data.0.print();
    data.0.print();
    let logger2 = Logger2 { score: 2 };
    data.0 = box logger2;
    data.0.print();
    data.0.print();
}
PS Z:\rust\study\test001> cargo run 
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target\debug\test001.exe`
Logger { age: 2 }
Logger { age: 3 }   
Logger2 { score: 3 }
Logger2 { score: 4 }
PS Z:\rust\study\test001> 

作者 ‘static 2020-09-20 10:26

3Q!大佬我还想问问,主要逻辑要写在被c语言多次调用的回调函数里,类似事件触发,这种情况下我首先想到的就是如题的全局变量,为了灵活一点,用全局trait变量,有没有方法实现?或者不用全局变量的话,有其他思路,让回调函数多次被调用时,访问的是同一个值? fn call_back(){//一个c的回调函数 会被多次调用 函数已被限定死 无法调整参数 //主要逻辑在里面 //多次调用中 如何访问到同一个函数外的数据
}

-- Q 👇
whfuyn: h是本地变量,函数结束就没了,全局变量拿着个野指针。

whfuyn 2020-09-19 23:57

h是本地变量,函数结束就没了,全局变量拿着个野指针。

1 共 6 条评论, 1 页