With SoapySDR you open a Device (Device in soapysdr - Rust) and get a struct instance in return. Using the Device a stream can be opened using the rx_stream method. The returned RxStream (RxStream in soapysdr - Rust) instance keeps a back reference to the device it was opened on, so the Device instance must live longer than the RxStream instance – entirely reasonable. There is no problem if you write code in which the Device instance is opened and closed in the same scope. However, I need to open the device and stream in one function and close it in another. This seems like a job for a struct that takes ownership. I have tried:
I am sure I should understand what needs to be done to get round this, but having randomly tried lots of stuff, I am going round in ever decreasing circles. Has anyone out there seen this sort of thing and discovered a way out?
but this does not satisfy the compiler. Whenever I try to implement a trait for this struct, I get errors along the lines of:
error[E0478]: lifetime bound not satisfied
--> src/soapysdrsrc.rs:127:10
|
127 | impl<'a> ObjectImpl for SoapySDRSrc<'a> {
| ^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 127:6
--> src/soapysdrsrc.rs:127:6
|
127 | impl<'a> ObjectImpl for SoapySDRSrc<'a> {
| ^^
= note: but lifetime parameter must outlive the static lifetime
You're attempting to create a self-referential struct, which (in short) Rust doesn't allow - if you search that phrase, you'll see a good amount of prior discussion. SoapySDRSrc would own the Device and also own the RxStream, but the latter is borrowing from the device - this leads to SoapySDRSrc borrowing from itself, which is the self referencing aspect.
Your best bet is to rearrange the code to avoid this type of setup - see if you can own the Device separate from the RxStream. You can also look into using a crate like rental, which can facilitate some self-referential use cases (at the cost of ergonomics).
The error you asked about is what you get if ObjectImpl requires 'static. That is, it's defined like this (or some variation):
pub trait ObjectImpl: 'static { ... }
You can't fix this error by removing the Device from SoapySDRSrc, even though that would solve the self-borrowing problem, because anything that implements ObjectImpl is forbidden to borrow non-'static data.
rental might still work, depending on what API you need to expose. Note that it's not just ergonomics you give up; you also have to Box the Device so that the RxStream remains valid when the whole struct is moved (e.g., to pass into or return from a function).
Also look into owning_ref, which is another crate that enables self-borrowing structs.
actually mean and why they are the way they are. They seem to deny a struct with any field that requires an explicit lifetime. I'll take this to the gtk-rs folk.
it turns out that in this case, using gtk-rs and gstreamer-rs, all objects of type SoapySDRSrc and all fields must be on the heap. TIL lots of stuff about Rust, gtk-rs and gstreamer-rs; today is a good day.