I created a Rust wrapper for a C++ library for a camera using bindgen, and the camera handle in the C++ library is defined as typedef void camera_handle
which bindgen ported over as:
pub type camera_handle = ::std::os::raw::c_void;
I'm able to successfully connect to the camera and take images, however I wanted to run code on a separate thread for temperature control of the camera, essentially changing the cooler power based on the current temperature of the camera, which I want to have run separately from the rest of the code. These calls require the camera handle, but when I spawn a new thread, I keep getting the error:
'*mut std::ffi::c_void' cannot be sent between threads safely
And underneath it, it mentions:
the trait 'std::marker::Send' is not implemented for '*mut std::ffi::c_void'
How can I send this to another thread so I can use this camera handle there as well? I have tried using fragile and send_wrapper, but have been unsuccessful with both of them.
Pointers do not implement Send
or Sync
since their safety escapes the compiler. You are intended to explicitly indicate when a pointer is safe to use across threads. This is typically done via a wrapper type that you implement Send
and/or Sync
on yourself:
struct CameraHandle(*mut c_void);
unsafe impl Send for CameraHandle {}
unsafe impl Sync for CameraHandle {}
Since implementing these traits manually is unsafe
, you should be extra diligent to ensure that the types from the external library actually can be moved another thread (Send
) and/or can be shared by multiple threads (Sync
).
If you ever take advantage of the pointer's mutability without the protection of &mut self
, it should probably not be Sync
since having two &mut T
at the same time is always unsound.
See: