How to convert an address to a function generated by bindgen?

Hello, I am making a function call from Rust code to C code. The C code is a binary blob and not compiler by me. All I know about this binary blob is the entry point of a particular function.

Here is the function declaration in C:

typedef EFI_STATUS (EFIAPI *FSP_MEMORY_INIT) (VOID* FspmUpdDataPtr, VOID **HobListPtr);

When I run bindgen on this function declaration, I get:

pub type FSP_MEMORY_INIT = ::core::option::Option<unsafe extern "win64" fn(FspmUpdDataPtr: *mut ::core::ffi::c_void, HobListPtr: *mut *mut ::core::ffi::c_void) -> EFI_STATUS>;

Supposing I have an address stored in a usize variable called fsp_base, how do I convert this address to this function pointer type?

What has stumped me in doing the conversion is the Option type. If I write out the same function typedef without the Option, I can easily transmute:

type FspMemoryInit = unsafe extern "win64" fn(
    FspmUpdDataPtr: *mut core::ffi::c_void,
    HobListPtr: *mut *mut core::ffi::c_void,
) -> efi::EFI_STATUS;
let fspm = core::mem::transmute::<usize, FspMemoryInit>(fsp_base);

My goal is to use bindgen. How can I accomplish this same conversion with the function type generated by bindgen?

You can transmute straight to Option<fn>, because Rust guarantees that Option<function> is the same as a bare nullable function pointer in C.

Alternatively, cast first, and then wrap in Some(fnptr).

Do note however that Rust does not guarantee the size of function pointer and data pointer (so usize too) are the same

Turning a pointer into a function pointer. This is not portable to machines where function pointers and data pointers have different sizes.

This is usually true though it is guaranteed that function pointers are of the same size like in C, however.

transmute catches wrong input sizes at compile time, so I think it should be safe and reliable when it compiles, just not portable to exotic platforms.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.