Use opaque pointers (*mut c_void or *const c_void) in Rust FFI to hide the concrete type from the C side while maintaining safety via unsafe blocks. Define the pointer type in your Rust struct or function signature, cast it to the concrete type inside an unsafe block, and ensure the C side only passes the raw pointer without dereferencing it.
use std::ffi::c_void;
// Rust side: define a struct and a function accepting an opaque pointer
struct MyData {
value: i32,
}
#[no_mangle]
pub extern "C" fn process_data(ptr: *mut c_void) {
unsafe {
// Cast the opaque pointer to the concrete type
let data = &mut *(ptr as *mut MyData);
data.value += 1;
}
}
On the C side, declare the function to accept void* and pass the address of your struct without casting it to a specific type in C.