为何从引用转换为c_void指针需要双重转换?
as *mut *mut _ Cast is Required in FFI Calls Let's break down why that intermediate cast is necessary, and what type the compiler infers for _.
1. The Type Conversion Chain Explained
First, let's map out the types step by step for your working code:
baris of type*mut foo&mut barcreates a mutable reference:&mut *mut foo- The first cast
as *mut *mut _tells Rust to convert that mutable reference into a raw pointer matching the underlying nested type. The compiler infers_asfoo, so this cast produces*mut *mut foo - The second cast
as *mut *mut c_voidconverts*mut *mut footo*mut *mut c_void—this is allowed because Rust explicitly permits converting raw pointers to/from*mut c_void(the FFI standard for "generic pointers").
2. Why Direct Conversion Fails
When you skip the intermediate step and write &mut bar as *mut *mut c_void, Rust rejects it because its casting rules don't support jumping directly from a mutable reference (&mut *mut foo) to a raw pointer of a different nested pointer type (*mut *mut c_void).
Rust requires explicit, incremental steps here:
- First, convert the mutable reference to a raw pointer of the exact same nested type (
*mut *mut foo). This is a safe, straightforward cast since&mut Tcan always be converted to*mut T. - Then, convert that raw pointer to the target FFI-compatible type (
*mut *mut c_void). Raw pointers to any type can be cast to pointers toc_void, so this step is valid.
3. What the *-ptr Error Message Means
When you tried assigning &mut bar as *mut *mut _ to a u8, the compiler's *-ptr message is just a shorthand for "a raw pointer type"—specifically, it refers to *mut *mut foo. The compiler uses this generic term to highlight the type mismatch between the pointer and your expected u8, not because the type is unknown.
A More Explicit Alternative
If you want to remove ambiguity, you can write the intermediate type explicitly instead of using _—it does the exact same thing:
struct foo; let mut bar: *mut foo = std::ptr::null_mut(); unsafe { ffi(&mut bar as *mut *mut foo as *mut *mut std::os::raw::c_void); }
内容的提问来源于stack exchange,提问作者Ryan C.

