Rust SDL2定时器:我如何从函数返回定时器对象?



我正在使用sdl2 crate,我正在尝试创建一个简单的"上下文";带有计时器的对象。我有以下代码

extern crate sdl2;
struct Ctx<'a, 'b> {
timer: sdl2::timer::Timer<'a, 'b>,
}
impl<'a,'b> Ctx<'a, 'b> {
pub fn new() -> Ctx<'a,'b> {
let sdl_context = sdl2::init().unwrap();
let timer_subsystem = sdl_context.timer().unwrap();
let timer = timer_subsystem.add_timer(100, Box::new(|| -> u32 { 100 }));
Ctx { timer }
}
}
pub fn main() {
let _ = Ctx::new();
}

问题是add_timer()似乎借用了timer_子系统对象,它阻止了计时器从函数中移出。

error[E0515]: cannot return value referencing local variable `timer_subsystem`
--> src/main.rs:13:9
|
11 |         let timer = timer_subsystem.add_timer(100, Box::new(|| -> u32 { 100 }));
|                     ----------------------------------------------------------- `timer_subsystem` is borrowed here
12 |
13 |         Ctx { timer }
|         ^^^^^^^^^^^^^ returns a value referencing data owned by the current function

然而,如果我查看add_timer(),我不明白为什么引用被认为仍然存在。事实上,self引用根本没有在函数中使用:https://docs.rs/sdl2/latest/src/sdl2/timer.rs.html 17-32

pub fn add_timer<'b, 'c>(&'b self, delay: u32, callback: TimerCallback<'c>) -> Timer<'b, 'c> {
unsafe {
let callback = Box::new(callback);
let timer_id = sys::SDL_AddTimer(
delay,
Some(c_timer_callback),
mem::transmute_copy(&callback),
);
Timer {
callback: Some(callback),
raw: timer_id,
_marker: PhantomData,
}
}
}

我试图把timertimer_subsystemCtx(以确保他们的寿命是相同的),但它没有帮助。两者都没有使用Box<>包装它们(以防止在timer_子系统被移动后出现悬空指针),但两者都不起作用。

为什么我在这里引用了本地数据,我如何才能正确返回timer对象?

秘密在PhantomDataTimer内部声明的完整类型是PhantomData<&'b ()>,'badd_timer()中指定为&'b self。这将返回的Timer的生命周期与TimerSubsystem的生命周期绑定在一起。这是因为当子系统被丢弃时,它被关闭,并且之后不允许访问计时器。

最好的选择可能是在调用Ctx::new()并将其作为参数传递之前初始化计时器子系统(和SDL),因为很难同时存储子系统和计时器(一个自引用结构体)。

最新更新