2

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.

kmdreko
  • 42,554
  • 6
  • 57
  • 106
EmaadP
  • 160
  • 1
  • 1
  • 10
  • that have nothing to do with `c_void` you try to send the mutable pointer of something. That not allowed – Stargateur Sep 22 '21 at 23:56
  • @Stargateur Sending a mutable pointer is fine, it's a mutable reference that is forbidden from being shared - and converting a pointer to a reference requires an unsafe block. Rust additionally requires manually and unsafely implementing `Send` for pointers as precaution and a reminder to check that the pointers are used in accordance with Rust's rules. If the OP is only using the pointer for FFI, they should be safe (provided that the foreign API is itself thread safe). – user4815162342 Sep 23 '21 at 08:53

1 Answers1

7

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:

kmdreko
  • 42,554
  • 6
  • 57
  • 106