sync-ptr
Sync & Send wrappers for raw pointer's and function pointers in rust.
This crate uses #![no_std] and can be used in projects that do not use the rust standard library.
Minimum rust version is rust 1.65.0
Intended use
This crate is intended for handles or pointers to data behind an FFI boundary that is known to be Send or Sync.
Example where this is most likely the case:
- shared memory from mmap() or MapViewOfFile()
- global JNI handles
- ffi mutex handles etc
- ffi function pointers
- ...
I would like to mention that this crate does not magically make any C/FFI pointers into arbitrary data Send or Sync safely. Using pointers/handles from a different thread can be UB in rust, or you may cause UB on the C/FFI side.
This crate is not intended for usage with pointers to rust data. While it can be used like this, one has to be VERY careful to avoid UB.
Example
use c_void;
use null_mut;
use *;
Why not just make RustControlStructureThatIsNowSend implement Send directly?
This is prone to error as once a struct is "unsafe impl Sync," for example, it will be Sync no matter what struct members get added later. If the initial reason for that unsafe impl was a raw pointer, then the compiler has no opportunity to inform the Human that adding a RefCell to such a struct is maybe not a good idea.
In addition, there are sometimes cases where one only needs to send a single pointer, and writing an unsafe impl wrapper struct everytime is annoying.
Function pointers
While you can use the SyncConstPtr for example to wrap your raw function pointers, by first casting them to a pointer type like c_void,
doing this is cumbersome as it requires you to transmute the pointer back to a function pointer every time you want to use it.
To make this easier this crate provides a specialized wrapper for function pointers
that allows you to call the function without unsafe code or specifying the signature every time.
The two wrappers are called SyncFnPtr and SendFnPtr.
These wrappers are not provided by default because they rely on rust features that were only stabilized in rust 1.85.0. If your msrv is 1.85.0 or newer, then use the "fnptr" feature to enable this.
Null Function pointers
Rust does not support null function pointers,
but since null function pointers are very common in FFI this crate does support them.
SyncFnPtr and SendFnPtr both impl Default as well as provide a null constructor,
which provides such a null function pointer. If you attempt to call a null function pointer
then your program is guaranteed to panic.
Internally both wrappers use repr(transparent) of Option<fn(...) -> ...> granting it the same layout.
This makes the wrappers suitable for use in FFI structs.
Constructing the function pointer wrapper
Unfortunately the trait core::marker::FnPtr is unstable, this prevents this crate from providing
a convenient safe constructor function for the wrappers.
The only way to construct the wrappers (other than using null/default) is using one of the 4 provided macros:
send_fn_ptr!- For use with rust functions onlysync_fn_ptr!- For use with rust functions onlysend_fn_ptr_from_addr!- For use with usize/raw pointersync_fn_ptr_from_addr!- For use with usize/raw pointer
Example
Constructing these wrappers from rust functions does not require unsafe code, but constructing them from raw pointers or usize does need unsafe code.
use c_void;
use send_fn_ptr;
use send_fn_ptr_from_addr;
use SendFnPtr;
extern "C"