Casts of the type _ as f-ptr
are not allowed (see the Rustonomicon chapter on casts). So, as far as I can tell, the only way to cast to function pointer types is to use the all mighty weapon mem::transmute()
.
But before we can use transmute()
, we have to bring our input into the right memory layout. We do this by casting to *const ()
(a void pointer). Afterwards we can use transmute()
to get what we want:
let ptr = virtual_address as *const ();
let code: extern "C" fn() = unsafe { std::mem::transmute(ptr) };
(code)();
If you find yourself doing this frequently, various kinds of macros can remove the boilerplate. One possibility:
macro_rules! example {
($address:expr, $t:ty) => {
std::mem::transmute::<*const (), $t>($address as _)
};
}
let f = unsafe { example!(virtual_address, extern "C" fn()) };
f();
However, a few notes on this:
- If you, future reader, want to use this to do simple FFI things: please take a moment to think about it again. Calculating function pointers yourself is rarely necessary.
- Usually
extern "C"
functions have the type unsafe extern "C" fn()
. This means that those functions are unsafe to call. You should probably add the unsafe
to your function.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…