我试图编写一个函数,将命令行实用程序(image-magick)的标准输出加载到结构的成员中。我认为由于图像可以是MB,所以我最好避免复制。
/// An image data container used internally.
/// Images are 8-bit single channel for now.
pub struct Image<'a> {
/// Width of the image in pixels.
pub width: u32,
/// Height of the image in pixels.
pub height: u32,
/// The buffer containing the image data, as a slice.
pub pixels: &'a [u8],
}
// Load a file by first using imageMagick to convert it to a .pgm file.
fn load_using_magick<'a>(path: Path) -> Image<'a> {
use std::io::Command;
let output:IoResult<ProcessOutput> = Command::new("convert")
.arg("-format pgm")
.arg("-depth 8")
.arg(path)
.arg("-")
.output();
let output_unwrapped:ProcessOutput = match output {
Ok(o) => o,
Err(e) => panic!("Unable to run ImageMagick's convert tool in a separate process! convert returned: {}", e),
};
let bytes: &[u8] = match output_unwrapped.status.success() {
false => panic!("signal or wrong error code from sub-process?"),
true => output_unwrapped.output.as_slice(),
};
// Note, width and height will eventually get parsed out of "bytes"
// and the returned Imaeg.pixels will point to a slice of the (already)
// heap allocated memory. I just need to figure out ownership first...
Image{width:10,height:10,pixels:bytes}
}
当标准库std :: io :: Process :: Command :: output()被调用时,我想保留的一大堆内存是由标准库(或内核?)分配的。
借阅检查器编译失败:
src/loaders.rs:41:17: 41:40 error: `output_unwrapped.output` does not live long enough
src/loaders.rs:41 true => output_unwrapped.output.as_slice(),
^~~~~~~~~~~~~~~~~~~~~~~
src/loaders.rs:21:51: 48:2 note: reference must be valid for the lifetime 'a as defined on the block at 21:50...
src/loaders.rs:21 fn load_using_magick<'a>(path: Path) -> Image<'a> {
src/loaders.rs:22 use std::io::Command;
src/loaders.rs:23
src/loaders.rs:24 let output:IoResult<ProcessOutput> = Command::new("convert")
src/loaders.rs:25 .arg("-format pgm")
src/loaders.rs:26 .arg("-depth 8")
...
src/loaders.rs:21:51: 48:2 note: ...but borrowed value is only valid for the block at 21:50
src/loaders.rs:21 fn load_using_magick<'a>(path: Path) -> Image<'a> {
src/loaders.rs:22 use std::io::Command;
src/loaders.rs:23
src/loaders.rs:24 let output:IoResult<ProcessOutput> = Command::new("convert")
src/loaders.rs:25 .arg("-format pgm")
src/loaders.rs:26 .arg("-depth 8")
这对我来说很有意义;我试图保留的所有数据块都超出了范围,在我按值返回的结构中留下了一个悬空指针。那么,在返回该存储区之前,我该如何将其所有权真正转移到我的结构上呢?
我已经阅读了Rust生时手册。
您的签名声称,无论呼叫者希望的生存时间如何,您都可以返回Image<'that_lifetime>
。实际上,您声称要返回Image<'static>
,其中包含一个&'static [u8]
,即指向字节片的指针,该字节片在程序执行的整个过程中都有效。显然,ProcessOutput
您实际从中获取字节片的起始时间并不长。
该存储器区域的所有权属于output_unwrapped
,更具体地output_unwrapped.output
(一个Vec<u8>
)。您需要保留这两个中的一个。最简单的选择是将所有权授予Image
:创建pixels
一个Vec<u8>
,然后移出output_unwrapped
。当然,这会对所有代码处理产生持久影响Image
,因此这是一个设计问题。它使意识为自己内容的图像?借款不足是否会给任何预期的使用案例带来问题?(如果您无法回答这些问题,尽管您可能只能在几周后才能找到答案,但是您可以随时尝试一下。)
一种选择是对所有权进行抽象,即允许向量和切片。通过std::borrow::Cow<[u8]>
类型,甚至在标准库中也支持。您只需要确定是否值得额外的麻烦,尤其是由于pixels
某种原因(可能不是一个好人?)是公开的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句