我正在使用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\u timer()似乎borrow 了timer\u子系统对象,它阻止了计时器移出函数.

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参考:

    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_subsystem放在Ctx之间(以确保它们的生命周期 是一样的),但没有用.两者都没有用Box<>包装(以防止在timer_子系统移动后指针悬空),但都不起作用.

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

推荐答案

秘密在PhantomData.The full type as declared inside Timer is PhantomData<&'b ()>'b is specified as &'b self in add_timer().这将返回的Timer的生存期与TimerSubsystem的生存期联系起来.这是因为when the subsystem is dropped it is shutted down,之后不允许访问计时器.

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

Rust相关问答推荐

将内部类型作为参数的泛型 struct 上的方法

MacOS(AARCH64)上Ghidra中的二进制补丁导致进程终止

使用pyo3::Types::PyIterator的无限内存使用量

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

Box::new()会从一个堆栈复制到另一个堆吗?

告诉Rust编译器返回值不包含构造函数中提供的引用

字段类型为Boxed的 struct 的生存期必须超过static

作为1字节位掩码的布尔值 struct

rust 蚀生命周期 不匹配-不一定超过此处定义的生命周期

不同类型泛型的映射

返回Result<;(),框<;dyn错误>>;工作

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

带引脚和不带引脚的比较功能

write_buffer 不写入缓冲区而是输出零 WGPU

Rust 打包在 .deb 中

在多核嵌入式 Rust 中,我可以使用静态 mut 进行单向数据共享吗?

第 7.4 章片段中如何定义 `thread_rng`

在 Rust 中如何将值推送到枚举 struct 内的 vec?

我可以在不调用 .clone() 的情况下在类型转换期间重用 struct 字段吗?

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?