There are several questions on SO asking this same thing:
Is there a way to store a texture inside a struct using rust-sdl2?
Managing SDL2 (rust) Texture lifetime
And these were supposedly answered in:
Cannot infer an appropriate lifetime for autoref due to conflicting requirements
Why can't I store a value and a reference to that value in the same struct?
I also looked at the examples in the rust-sdl2 repo, but I still can't figure this out.
My goal is to have a struct that holds a canvas and a texture so I can repeatedly update the texture with new pixel data from a streaming camera. I got this to work but I was creating a new texture in every loop iteration which didn't seem right and also caused a memory leak. So I decided to hold the texture in a struct and just update it on every call to draw
. This seemed like the right thing to do, but rust-sdl makes this seemingly impossible due to lifetime constraints on Texture
. I followed the compiler suggestions about adding lifetimes and what not, but now I'm stuck. Here's what I have so far:
use sdl2::pixels::PixelFormatEnum;
use sdl2::render::{Canvas, Texture, TextureCreator};
use sdl2::video::{Window, WindowContext};
pub struct View<'tex> {
canvas: Canvas<Window>,
texture: &'tex Texture<'tex>,
}
impl<'tex> View<'tex> {
fn new(width: u32, height: u32) -> Self {
let sdl_context = sdl2::init().unwrap();
let subsystem = sdl_context.video().unwrap();
let window = subsystem
.window("sdl2 - test", width, height)
.position_centered()
.build()
.unwrap();
let canvas = window.into_canvas().build().unwrap();
let texture_creator: &'tex TextureCreator<WindowContext> = &canvas.texture_creator();
let texture: &'tex Texture = &texture_creator
.create_texture_streaming(PixelFormatEnum::ARGB8888, width as u32, width as u32)
.map_err(|e| e.to_string()).unwrap();
Self {
canvas,
texture,
}
}
}
fn main() {
let view = View::new(500, 500);
}
But I am stuck at this error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:23:69
|
11 | impl<'tex> View<'tex> {
| ---- lifetime `'tex` defined here
...
23 | let texture_creator: &'tex TextureCreator<WindowContext> = &canvas.texture_creator();
| ----------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'tex`
...
32 | }
| - temporary value is freed at the end of this statement
I also thought about creating the canvas and the texture in main
and passing them to new
so that they &'static
lifetime, but that goes down another rabbit hole where I need to also create the window in main
and pretty much negates any kind of abstraction I was attempting.
How do I store a reference to the Texture so I can avoid repeatedly allocating it?