我使用rust-sfml
(rsfml::graphics
),目前,绘制像素到屏幕上。(我刚刚开始学习Rust和这个项目。)我将数据存储在Image
中,然后复制到Texture
。
这个Texture
用来创建一个Sprite<'s>
;这就是我的问题所在。我需要能够突变Texture
,但Sprite<'s>
的类型似乎保证我不能做我想做的。因为我需要能够调用window.draw(&sprite)
每次窗口重绘,我只是创建一个新的Sprite
每次。
更可取的选择是将Sprite<'s>
与Texture
一起保留在struct Render
中。因为'Sprite'有一个生命周期参数,所以它变成了struct Render<'s>
:
struct Render<'s> {
texture: Texture,
sprite: Sprite<'s>,
}
我在Render
上有一个方法:
fn blit(&'s mut self) -> ()
改变Render
(通过编辑Texture
)。现在,只要我尝试多次调用blit
,我就会遇到这个问题:
render.blit();
render.blit(); // error: cannot borrow `render` as mutable more than once at a time
,我认为,这是因为lifetime参数强制Render
的lifetime-as- by-the-first- blit
-call等于Render
实例(整个main函数)的lifetime。
我怎样才能保持原来的Sprite
并继续能够改变容器?这可能吗?
这是一个看起来很傻,相当简单的例子:
extern crate rsfml;
use rsfml::graphics::Sprite;
fn main() -> () {
let mut render = Render::new();
render.blit();
render.blit(); // error: cannot borrow `render` as mutable more than once at a time
}
struct Render<'s> {
sprite: Option<Sprite<'s>>,
}
impl<'s> Render<'s> {
fn new() -> Render { Render { sprite: None } }
fn blit(&'s mut self) -> () { }
}
如果问题不清楚,请向我道歉。当我不太熟悉这些概念时,很难表达出来。
调用blit
时,会考虑两个生命周期;你看,self
在某些寿命期是&'ρ₀ Render<'ρ₁>
型的ρ 0和ρ 1。在你的impl<'s> Render<'s>
声明中,你已经声明ρ₁是's
,在你的&'s mut self
声明中,你已经声明ρ₁是's
:因此,self
的借用寿命是's
,这意味着你只能有一个借用,因为它将存活到类型的破坏-它已被声明为"至少与所引用的类型一样长"。
你想为blit
函数引入一个新的生命周期参数,允许小于's
;你希望ρ 0是最小的,只绑定到返回值(我假设你实际上是使用's
-如果不是,你应该忽略它,并允许编译器推断我们要显式地写什么)。这样,借用将只在函数的返回值仍在作用域中时才被激活(在您的简单示例中,它没有被使用,因此您可以立即接受另一个引用)。
这就是需要对函数做的修改:
fn blit<'a>(&'a mut self) { }
如果您将其更改为具有返回值并使用它,则需要在再次调用blit
之前确保它超出作用域。这可能意味着将其直接传递给函数,也可能意味着引入一个新的作用域,像这样:
{
let foo = render.blit();
// … do things with foo … it then gets freed at the end of the block.
}
render.blit();