I'm building an easy to use interface for the libuvc camera-library in Rust. I want to define a Camera
type that is easy to set up. I'm using libuvc-rs as an interface to the libuvc c-library. Setting up a camera using libuvc requires calling a number of functions that each return handles used to perform different functions in the uvc library. My struct UvcCamera
, therefore, contains one of each of these types for operation:
pub struct UvcCamera<'a> {
ctx: uvc::Context<'a>,
dev: uvc::Device<'a>,
devh: uvc::DeviceHandle<'a>,
streamh: uvc::StreamHandle<'a>,
}
I cannot create a function that legally initializes these variables. Importantly, the function doesn't return a reference but an owned object. The struct members are also not references but owned objects. No matter the approach I choose, I end up with some kind of borrowing error (and I have searched the internet endlessly for similar problems but without luck). The most straightforward implementation is shown below:
impl<'a> UvcCamera<'a> {
pub fn new() -> uvc::Result<UvcCamera<'a>> {
let serial = UvcCamera::serial_number_from_uid(1)?;
let ctx: uvc::Context<'a> = uvc::Context::new()?;
let dev = ctx.find_device(None, None, Some(&serial))?;
let devh = dev.open()?;
let format = uvc::StreamFormat {
width: 640,
height: 480,
fps: 60,
format: uvc::FrameFormat::MJPEG,
};
let streamh = devh.get_stream_handle_with_format(format)?;
Ok(UvcCamera { ctx, dev, devh, streamh })
}
This results in the error
error[E0515]: cannot return value referencing local variable `devh`
--> src/camera.rs:36:9
|
35 | let streamh = devh.get_stream_handle_with_format(format)?;
| ---- `devh` is borrowed here
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `dev`
--> src/camera.rs:36:9
|
26 | let devh = dev.open()?;
| --- `dev` is borrowed here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `ctx`
--> src/camera.rs:36:9
|
25 | let dev = ctx.find_device(None, None, Some(&serial))?;
| --- `ctx` is borrowed here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `ctx` because it is borrowed
--> src/camera.rs:36:24
|
20 | impl<'a> UvcCamera<'a> {
| -- lifetime `'a` defined here
...
25 | let dev = ctx.find_device(None, None, Some(&serial))?;
| --- borrow of `ctx` occurs here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ---------------^^^-----------------------
| | |
| | move out of `ctx` occurs here
| returning this value requires that `ctx` is borrowed for `'a`
error[E0505]: cannot move out of `dev` because it is borrowed
--> src/camera.rs:36:29
|
20 | impl<'a> UvcCamera<'a> {
| -- lifetime `'a` defined here
...
26 | let devh = dev.open()?;
| --- borrow of `dev` occurs here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| --------------------^^^------------------
| | |
| | move out of `dev` occurs here
| returning this value requires that `dev` is borrowed for `'a`
error[E0505]: cannot move out of `devh` because it is borrowed
--> src/camera.rs:36:34
|
20 | impl<'a> UvcCamera<'a> {
| -- lifetime `'a` defined here
...
35 | let streamh = devh.get_stream_handle_with_format(format)?;
| ---- borrow of `devh` occurs here
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| -------------------------^^^^------------
| | |
| | move out of `devh` occurs here
| returning this value requires that `devh` is borrowed for `'a`
error[E0515]: cannot return value referencing local variable `devh`
--> src/camera.rs:36:9
|
35 | let streamh = devh.get_stream_handle_with_format(format)?;
| ---- `devh` is borrowed here
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `dev`
--> src/camera.rs:36:9
|
26 | let devh = dev.open()?;
| --- `dev` is borrowed here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `ctx`
--> src/camera.rs:36:9
|
25 | let dev = ctx.find_device(None, None, Some(&serial))?;
| --- `ctx` is borrowed here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `ctx` because it is borrowed
--> src/camera.rs:36:24
|
20 | impl<'a> UvcCamera<'a> {
| -- lifetime `'a` defined here
...
25 | let dev = ctx.find_device(None, None, Some(&serial))?;
| --- borrow of `ctx` occurs here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| ---------------^^^-----------------------
| | |
| | move out of `ctx` occurs here
| returning this value requires that `ctx` is borrowed for `'a`
error[E0505]: cannot move out of `dev` because it is borrowed
--> src/camera.rs:36:29
|
20 | impl<'a> UvcCamera<'a> {
| -- lifetime `'a` defined here
...
26 | let devh = dev.open()?;
| --- borrow of `dev` occurs here
...
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| --------------------^^^------------------
| | |
| | move out of `dev` occurs here
| returning this value requires that `dev` is borrowed for `'a`
error[E0505]: cannot move out of `devh` because it is borrowed
--> src/camera.rs:36:34
|
20 | impl<'a> UvcCamera<'a> {
| -- lifetime `'a` defined here
...
35 | let streamh = devh.get_stream_handle_with_format(format)?;
| ---- borrow of `devh` occurs here
36 | Ok(UvcCamera { ctx, dev, devh, streamh })
| -------------------------^^^^------------
| | |
| | move out of `devh` occurs here
| returning this value requires that `devh` is borrowed for `'a`
Importantly, all the libuvc types implement Drop
(logical since they hold references that need to be freed) and therefore can't derive Copy
. Is there any way constructing this kind of type is possible?