ruabmbua / hidapi-rs

Rust bindings for the hidapi C library
MIT License
172 stars 81 forks source link

Trying to store a hidapi::HidDevice in a struct #16

Closed shayne closed 6 years ago

shayne commented 6 years ago

Hey there, thanks for the library!

I'm working on a project to abstract away a device. So simply put, I'm looking to store the hidapi::HidDevice that I open in a struct so my API can call read/write on it as necessary.

It's easy enough to store the api, but once I try to store the device (alone or with api) I get lifetime issues. Perhaps this has to do with the PhantomData you have on HidDevice?

I'm probably just missing something with Rust but I've been struggling to abstract away the HidApi from my library.

ruabmbua commented 6 years ago

Hi! Take a look at this PR, which will solve your problem. I ran into the same issue a while ago. Link: https://github.com/Osspial/hidapi-rs/pull/12

The PR is not yet merged, but you can always add my branch as a cargo git dependency if you want.

shayne commented 6 years ago

This is awesome, thanks for the quick response. I'll use your branch for now- glad I wasn't the only one who felt like it was a pain in the ***.

shayne commented 6 years ago

Hey @ruabmbua how are you sending the device between threads? Your PR mentions it but getting all sorts of errors.

ruabmbua commented 6 years ago

The HidDevice / API have to implement the Send trait, to be able to be shared safely between threads. My branch does not do this, and only solves the "store inside same struct" and "lifetime" issue.

My program is multi threaded, but relies on the gtk event queue, which solves synchronization issues for me.

When you want to access the API from multiple threads, try to spawn a handler thread, which owns / manages all your devices, and then pass std::sync::mpsc channels to it. You can then send your own custom messages from and to the hid IO thread safely.

ruabmbua commented 6 years ago

Tip: You can check if your type / instantiation can be shared between thready by doing this:

Remove the comments, to see the compilation errors for types, which do not implement Send.

std::rc::Rc does not implement send, because it has a non threadsafe reference counter inside. This is also true for all types, which embed the Rc type. There are also other types which do not implement send, like Raw pointers.

https://play.rust-lang.org/?gist=81b3dfd6d61db891b55fac499b354fe0&version=stable

shayne commented 6 years ago

Super helpful again - glad my thinking agreed with your assessment. Currently building out my final API using channels.

ruabmbua commented 6 years ago

@shayne finally my fork is merged now. I will release a new version to crates.io sometime soon.

shayne commented 6 years ago

Awesome thanks! I'll look at updating my end soon enough