I'm writing a safe struct wrapper for a C struct that holds a "user_data" void*
pointer. I'd like to use the void*
pointer to hold an arbitrary Rust, with all type safety and proper cleanup with Drop
.
To get a valid pointer I'm trying to use Box::new(rust_user_data)
& Box::into_raw() as *mut c_void
& Box::from_raw(void_ptr as *mut UserDataType)
.
I'm struggling with writing Drop
implementation for my wrapper, because Drop
doesn't allow specialization. I can't write impl<UserData> Drop for MyWrapper<Box<UserData>>
.
But if I write impl<BoxedUserData> Drop for MyWrapper<BoxedUserData>
I don't have a way to name the type in the Box in order to cast *mut c_void
to *mut UserData
(the pointer type is very important here, as Box
from *mut c_void
causes leaks/crashes).
struct CType {context: *mut c_void} // In practice it's an opaque data type
struct RustWrapper<UserDataType> {
handle: *mut CType,
_marker: PhantomData<UserDataType>,
}
// error[E0366]:
impl<UserDataType> Drop for RustWrapper<Box<UserDataType>> {
fn drop(&mut self) {
Box::from_raw(self.get_c_void_context_pointer() as *mut UserDataType)
}
}
Playpen: Rust Playground
So how can I get to the actual data in Box<T>
from Drop
?
As an added complication, I'd like to support RustWrapper<UserDataType = ()>
to make the user data optional. I can handle that by making the void*
NULL
.