When working with Foreign Function Interfaces (FFIs), I regularly see a double cast from reference-to-pointer-to-struct to pointer-to-pointer-to-void. For example, given an FFI-like function:
unsafe fn ffi(param: *mut *mut c_void) {}
The way to call this is:
struct foo;
let mut bar: *mut foo = ptr::null_mut();
unsafe { ffi(&mut bar as *mut *mut _ as *mut *mut c_void); }
Removing the intermediate cast yields this error:
error[E0606]: casting `&mut *mut foo` as `*mut *mut winapi::ctypes::c_void` is invalid
--> src\main.rs:36:18
|
36 | unsafe { ffi(&mut bar as *mut *mut c_void); }
|
I tried to get the compiler to tell me what the intermediate type is by forcing it into an obviously wrong type:
let mut bar: *mut foo = ptr::null_mut();
let mut test: u8 = &mut bar as *mut *mut _;
Which resulted in this error:
error[E0308]: mismatched types
--> src\main.rs:36:24
|
36 | let mut test: u8 = &mut bar as *mut *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found *-ptr
|
= note: expected type `u8`
found type `*mut *mut _`
But *-ptr
doesn't seem to be an actual type that I can put in place of _
. Why is the intermediate as *mut *mut _
required, and what is the inferred type?
I found this question which is related (Working with c_void in an FFI) but it doesn't actually explain anything about the double cast.