问题 return 从函数中调用 libusb::Device - 试图 return 值引用当前函数拥有的数据
Problem returning a libusb::Device from a function - attempting to return value referencing data owned by current function
我想连接 USB 设备,所以我使用 libusb。我有一个函数 return 是我感兴趣的设备的 libusb::Device
:
pub fn obtain_device() -> Device<'static> {
let context: Context = libusb::Context::new().unwrap();
let option: Device = context
.devices()
.unwrap()
.iter()
.find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda)
.unwrap();
option
}
然而这并不能编译:
error[E0515]: cannot return value referencing local variable `context`
--> src/usb/mod.rs:19:5
|
18 | let option: Device = context.devices().unwrap().iter().find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda).unwrap();
| ------- `context` is borrowed here
19 | option
| ^^^^^^ returns a value referencing data owned by the current function
根据我的理解,它是导致问题的 context
对象,即使它不是我从函数中 return 得到的对象。查看 libusb::Device
的定义
/// A reference to a USB device.
pub struct Device<'a> {
context: PhantomData<&'a Context>,
device: *mut libusb_device,
}
它包含对 Context
的引用,我认为这是编译失败的原因。但是我不确定如何从函数中 return a Device
或者我没有正确考虑应该如何编码。如果我想将 Device
对象传递给其他函数怎么办?
根据 Context::devices
的定义,Device<'a>
中的生命周期 'a
绑定到上下文的范围内,并且会变得无效(即会成为悬空指针)如果 Context
超出范围。也就是说,crate 不只是包装一些指向将永远存在的设备的指针,而是“通过”上下文访问设备。
处理这个问题的一种方法是使 Context
静态化,这样它就可以在程序的整个持续时间内存在。您可以使用 lazy_static
:
use lazy_static::lazy_static;
use libusb::{Context, Device};
lazy_static! {
static ref CONTEXT: Context = Context::new().unwrap();
}
pub fn obtain_device() -> Device<'static> {
CONTEXT
.devices()
.unwrap()
.iter()
.find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda)
.unwrap()
}
您还可以将您的函数转换为结构的方法,该结构拥有 Context
.
pub struct MyDeviceContext {
context: libusb::Context,
}
impl MyDeviceContext {
pub fn new(context: libusb::Context) -> Self {
Self { context }
}
pub fn obtain_device(&self) -> Device<'_> {
self.context
.devices()
.unwrap()
.iter()
.find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda)
.unwrap()
}
}
设备生命周期不再是 'static
,但只要 MyDeviceContext
仍在范围内就可以使用。
我想连接 USB 设备,所以我使用 libusb。我有一个函数 return 是我感兴趣的设备的 libusb::Device
:
pub fn obtain_device() -> Device<'static> {
let context: Context = libusb::Context::new().unwrap();
let option: Device = context
.devices()
.unwrap()
.iter()
.find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda)
.unwrap();
option
}
然而这并不能编译:
error[E0515]: cannot return value referencing local variable `context`
--> src/usb/mod.rs:19:5
|
18 | let option: Device = context.devices().unwrap().iter().find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda).unwrap();
| ------- `context` is borrowed here
19 | option
| ^^^^^^ returns a value referencing data owned by the current function
根据我的理解,它是导致问题的 context
对象,即使它不是我从函数中 return 得到的对象。查看 libusb::Device
/// A reference to a USB device.
pub struct Device<'a> {
context: PhantomData<&'a Context>,
device: *mut libusb_device,
}
它包含对 Context
的引用,我认为这是编译失败的原因。但是我不确定如何从函数中 return a Device
或者我没有正确考虑应该如何编码。如果我想将 Device
对象传递给其他函数怎么办?
根据 Context::devices
的定义,Device<'a>
中的生命周期 'a
绑定到上下文的范围内,并且会变得无效(即会成为悬空指针)如果 Context
超出范围。也就是说,crate 不只是包装一些指向将永远存在的设备的指针,而是“通过”上下文访问设备。
处理这个问题的一种方法是使 Context
静态化,这样它就可以在程序的整个持续时间内存在。您可以使用 lazy_static
:
use lazy_static::lazy_static;
use libusb::{Context, Device};
lazy_static! {
static ref CONTEXT: Context = Context::new().unwrap();
}
pub fn obtain_device() -> Device<'static> {
CONTEXT
.devices()
.unwrap()
.iter()
.find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda)
.unwrap()
}
您还可以将您的函数转换为结构的方法,该结构拥有 Context
.
pub struct MyDeviceContext {
context: libusb::Context,
}
impl MyDeviceContext {
pub fn new(context: libusb::Context) -> Self {
Self { context }
}
pub fn obtain_device(&self) -> Device<'_> {
self.context
.devices()
.unwrap()
.iter()
.find(|d| d.device_descriptor().unwrap().vendor_id() == 0x0bda)
.unwrap()
}
}
设备生命周期不再是 'static
,但只要 MyDeviceContext
仍在范围内就可以使用。