rust - 如何获取 rust-sdl2 窗口表面并同时使用事件迭代器?
问题描述
sdl2::video::Window::surface
需要对事件泵的可变引用,但是当我遍历事件泵给出的事件时sdl2::EventPump::wait_iter()
,事件泵被阻塞。
重现步骤:
创建一个新的货物项目:
$ cargo new foo
$ cd foo
$ echo 'sdl2 = "0.34.3"' >> Cargo.toml
用这个替换 src/main.rs :
extern crate sdl2;
use sdl2::event::Event;
use sdl2::event::EventType;
pub fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem.window("foo", 600, 600).build().unwrap();
let mut event_pump = sdl_context.event_pump().unwrap();
for event in event_pump.wait_iter() {
let mut wsuf = window.surface(&event_pump).unwrap();
}
}
不使用迭代器是一种解决方法。所以这个 main.rs 会做同样的事情,但是这个会编译:
use sdl2::event::Event;
use sdl2::event::EventType;
pub fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem.window("foo", 600, 600).build().unwrap();
let mut event_pump = sdl_context.event_pump().unwrap();
loop {
let event = event_pump.wait_event();
let mut wsuf = window.surface(&event_pump).unwrap();
}
}
这感觉不太惯用。
我看不出sdl2::video::Window::surface
借用事件泵的原因,尤其是在函数忽略该参数的情况下。看一下 sdl2::video::Window::surface 源代码
解决方案
这个函数的文档没有说明这个神秘的论点,所以我要做一个有根据的猜测。
首先,看函数Window::surface
声明:
pub fn surface<'a>(&'a self, _e: &'a EventPump) -> Result<WindowSurfaceRef<'a>, String>
并注意生命周期'a
在参数和返回的WindowSurfaceRef<'a>
. 所以只要返回值存在,self
和都会被借用。EventPump
查看代码,它是原生 SDL2-sys 函数的简单包装器SDL_GetWindowSurface()
,因此我们可以查看它的文档:
如有必要,将使用窗口的最佳格式创建一个新表面。当窗口被破坏时,这个表面将被释放。不要释放这个表面。
如果调整窗口大小,此表面将失效。调整窗口大小后,必须再次调用此函数以返回有效表面。
您不能将此与 3D 或此窗口上的渲染 API 结合使用。
关键词是粗体字。如果调整窗口大小,则此窗口将无效,这可能应解释为“如果您调整窗口大小然后使用此表面,则会导致未定义的行为”。
为了使这个包装器生锈安全,你必须避免在返回的生命周期内调整大小WindowSurfaceRef
。这是通过借用EventPump
: 来实现的,在EventPump
借用 时,不能处理任何消息,并且窗口不会调整大小。
请注意,为了借用EventPump
您不需要实际保留对它的引用,只需保留它的生命周期。通过归还WindowSurfaceRef<'a>
任何具有生命周期的东西'a
来保持借用。
文档中的最后一段,关于不在此窗口上使用呈现 API,以类似的方式实现,同时保持Window
借来的,具有相同的生命周期'a
。
推荐阅读
- makefile - Make没有意识到它已经完成了
- mysql - 数据库设计:X:X to 1:many vs X:X to 0:many
- javascript - 不带符号的 yup 字符串验证
- python - 如何在 export_graphviz 中调整图形大小?
- react-native - 在 React Native 中使用 FusionAuth
- json - jq - 如何格式化键和值对,然后在 json 中迭代键
- perl - Perl越狱
- excel - 如何在表格上搜索已编辑的行以比较值并相应地更改不同列上的时间戳?
- python-3.x - 如何模拟返回对象的函数?
- typescript - TypeOrm、Postgres 和 NestJS:过滤 ManyToMany 列