This is a small utility crate that provides the FnPtr trait, which is implemented for all function pointer types:
fn(T) -> Uunsafe fn(T) -> Uextern "C" fn(T)unsafe extern "sysv64" fn() -> i32
The trait provides associated types and constants to introspect function pointer types at compile time.
Every function pointer automatically implements FnPtr.
Depending on the type, they also implement SafeFnPtr,, UnsafeFnPtr, and HasAbi<Abi>.
With it you can inspect the type of function:
use fn_ptr::{FnPtr, Abi};
type F = extern "C" fn(i32, i32) -> i32;
assert_eq!(<F as FnPtr>::ARITY, 2);
assert_eq!(<F as FnPtr>::IS_SAFE, true);
assert_eq!(<F as FnPtr>::IS_EXTERN, true);
assert_eq!(<F as FnPtr>::ABI, Abi::C);There are also some const helper functons to do so ergonomically.
const A: usize = fn_ptr::arity::<F>(); // 2
const SAFE: bool = fn_ptr::is_safe::<F>(); // true
const EXT: bool = fn_ptr::is_extern::<F>(); // true
const ABI: Abi = fn_ptr::abi::<F>(); // Abi::CYou can toggle the safety of a function pointer at the type level:
use fn_ptr::{make_safe, make_unsafe};
type U = unsafe extern "C" fn(i32);
type S = make_safe!(U); // extern "C" fn(i32)
type S2 = extern "C" fn(i32);
type U2 = make_unsafe!(S2); // unsafe extern "C" fn(i32)Or at the instance level:
let safe_add: fn(i32, i32) -> i32 = |a, b| {a + b};
let unsafe_add: unsafe fn(i32, i32) -> i32 = safe_add.as_unsafe();
let safe_add2: fn(i32, i32) -> i32 = unsafe { unsafe_add.as_safe() };You can also change the ABI of a function pointer at the type level:
use fn_ptr::{with_abi, Abi};
type F = extern "C" fn(i32) -> i32;
type G = with_abi!(Abi::Sysv64, F);
type H = with_abi!("C", extern "system" fn());Or at the instance level:
use fn_ptr::{FnPtr, abi};
let rust_add: fn(i32, i32) -> i32 = |a, b| {a + b};
// Safety: not actually safe!
let c_add: extern "C" fn(i32, i32) -> i32 = unsafe { rust_add.with_abi::<{abi!("C")}>() };Note that this does not change the underlying ABI and should be used with caution.
To implement the traits for all function pointer types, there is a large macro.
For the conversion macros the crate relies on two traits: WithAbi and WithSafety that can also be used directly:
use fn_ptr::{FnPtr, WithAbi, WithSafety, Abi};
type F = extern "C" fn(i32);
type G = <F as WithAbi<{Abi::Sysv64}>>::F;
type U = <F as WithSafety<{false}>>::F;Licensed under the MIT license, see LICENSE for details.