Search code examples
rustfunction-pointersunsafe

Convert C function types in Rust


Consider we have two C function pointer types such as

uint32_t (*foo)(); 
uint32_t (*bar)(uint32_t);

From C perspective these types are compatible, so can be converted to each other.

Now consider we have a table of function pointers of type foo somewhere in the memory and we want to call them as either foo or bar from rust. For this we can have two types:

pub type FooFn = Option<unsafe extern "C" fn() -> u32>;
pub type BarFn = Option<unsafe extern "C" fn(u32) -> u32>;

Let's say we have obtained a function pointer:

let f: FooFn = unsafe {core::mem::transmute(FUNC_ADDRESS)};

but now I'd like to convert f into BarFn. I understand that it might be possible by reinterpreting the pointer again, as in

let b: BarFn = unsafe {core::mem::transmute(f)};

But is it the correct and well defined way to do so?


Solution

  • transmute() is the "correct" way to turn a function pointer into another type, but it is not the "best" due to being easy to misuse and call the incorrect type.

    A union is a good idea:

    #[repr(C)]
    union Fn {
        foo: Option<unsafe extern "C" fn() -> u32>,
        bar: Option<unsafe extern "C" fn(u32) -> u32>,
    }
    

    You are guaranteed that a None is a None, no matter from what field you assign or inspect it.