如何获得 rust-sdl2 window 表面并同时使用事件迭代器?
How to get a rust-sdl2 window surface and use the event iterator at the same time?
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
借用事件泵的原因,尤其是在函数忽略该参数的情况下。 Take a look at the sdl2::video::Window::surface source code
这个函数的文档没有提到这个神秘的论点,所以我打算做一个有根据的猜测。
首先看函数 Window::surface
declaration :
pub fn surface<'a>(&'a self, _e: &'a EventPump) -> Result<WindowSurfaceRef<'a>, String>
并注意生命周期 'a
用于两个参数和返回的 WindowSurfaceRef<'a>
。所以只要返回值存在,self
和EventPump
都会被借用。
看代码,它是原生SDL2-sys函数的简单包装SDL_GetWindowSurface()
,所以我们可以看一下它的documentation:
A new surface will be created with the optimal format for the window, if necessary. This surface will be freed when the window is destroyed. Do not free this surface.
This surface will be invalidated if the window is resized. After resizing a window this function must be called again to return a valid surface.
You may not combine this with 3D or the rendering API on this window.
关键词是加粗的。如果 window 被调整大小,那么这个 window 将失效,这可能应该被解释为“如果你调整 window 的大小然后使用这个表面你会导致未定义的行为”。
为了制作此包装器 Rusty-safe,您必须避免在返回的生命周期内调整大小 WindowSurfaceRef
。这是通过借用EventPump
来实现的:当借用EventPump
时,不能处理任何消息,并且不会调整window的大小。
请注意,为了借用 EventPump
你不需要实际保留对它的引用,只需要保留它的生命周期。通过返回一个 WindowSurfaceRef<'a>
任何生命周期为 'a
的东西都会被借用。
文档中的最后一段,关于在 window 上不使用 渲染 API,是以类似的方式实现的,同时保持Window
借用,生命周期相同 'a
.
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
借用事件泵的原因,尤其是在函数忽略该参数的情况下。 Take a look at the sdl2::video::Window::surface source code
这个函数的文档没有提到这个神秘的论点,所以我打算做一个有根据的猜测。
首先看函数 Window::surface
declaration :
pub fn surface<'a>(&'a self, _e: &'a EventPump) -> Result<WindowSurfaceRef<'a>, String>
并注意生命周期 'a
用于两个参数和返回的 WindowSurfaceRef<'a>
。所以只要返回值存在,self
和EventPump
都会被借用。
看代码,它是原生SDL2-sys函数的简单包装SDL_GetWindowSurface()
,所以我们可以看一下它的documentation:
A new surface will be created with the optimal format for the window, if necessary. This surface will be freed when the window is destroyed. Do not free this surface.
This surface will be invalidated if the window is resized. After resizing a window this function must be called again to return a valid surface.
You may not combine this with 3D or the rendering API on this window.
关键词是加粗的。如果 window 被调整大小,那么这个 window 将失效,这可能应该被解释为“如果你调整 window 的大小然后使用这个表面你会导致未定义的行为”。
为了制作此包装器 Rusty-safe,您必须避免在返回的生命周期内调整大小 WindowSurfaceRef
。这是通过借用EventPump
来实现的:当借用EventPump
时,不能处理任何消息,并且不会调整window的大小。
请注意,为了借用 EventPump
你不需要实际保留对它的引用,只需要保留它的生命周期。通过返回一个 WindowSurfaceRef<'a>
任何生命周期为 'a
的东西都会被借用。
文档中的最后一段,关于在 window 上不使用 渲染 API,是以类似的方式实现的,同时保持Window
借用,生命周期相同 'a
.