macro_rules! send_fn_ptr_from_addr {
($sig:ty, $var:expr) => { ... };
}Expand description
This macro creates a Function Pointer that is Send and guaranteed to have the same representation in memory as a raw function pointer would. (Meaning its size is usize)
§Null
This will not cause undefined behavior if a null pointer is used to create the function pointer. Unlike ordinary rust function pointers this type supports null pointers. Attempting to call a null function pointer will panic.
§Safety
This macro has to be placed in an unsafe block, because it accepts an arbitrary pointer as well as usize. The pointer/usize is interpreted as an address to a function. Should the pointer/usize not in fact be the address of a function with the given signature then this macro causes undefined behavior immediately.
The safe version of this macro is sync_fn_ptr! which only accepts a rust function type.
§Example
use std::ffi::c_void;
use sync_ptr::send_fn_ptr_from_addr;
use sync_ptr::SendFnPtr;
extern "C" fn test_function() -> u64 {
123456u64
}
fn some_function() {
//usually you would get this address from ffi/dlsym/GetProcAddress.
let some_address = test_function as *const c_void;
let test_fn_ptr = unsafe { send_fn_ptr_from_addr!(extern "C" fn() -> u64, some_address) };
//Type of test_fn_ptr is SendFnPtr<extern "C" fn() -> u64>
std::thread::spawn(move || {
assert_eq!(test_fn_ptr(), test_function());
}).join().unwrap();
}