The UnsafeCell
documentation says
The
UnsafeCell<T>
type is the only legal way to obtain aliasable data that is considered mutable.
The only construction method is:
pub const fn new(value: T) -> UnsafeCell<T>
However, it is not possible to create a c_void
, we can only create *mut c_void
or *const c_void
.
Is it possible to create UnsafeCell<c_void>
from a *mut c_void
? With this, we can let the compiler know that the pointer can point to something mutable.
Or is this not necessary? Can we always use *mut c_void
even we know some FFI call will mutate the data it points to and we have multiple references to it?
A use case would be:
struct FFIStruct { v: UnsafeCell<c_void>, other_fields: ... }
impl FFIStruct {
// We don't want to require &mut self, as we
// are sure private call_ffi() will always be called
// sequentially, and we don't want to stop
// status() being callable during the call
fn call_ffi(&self){ ffi_function(self.v.get()) }
pub fn status(&self) -> FFIStatus { ... }
}
Now how do we create FFIStruct
? Or just use *mut c_void
would be OK?
&Cell<c_void>
Requires #![feature(as_cell)]
:
unsafe fn get_cell<'a>(p: *mut c_void) -> &'a Cell<c_void> {
Cell::from_mut(&mut *p)
}
TL;DR: Just use *mut Foo
. Cells of any kind are not needed here.
Disclaimer: there is no formal Rust memory model, yet.
You cannot create this type, period, because you cannot1 create an instance of c_void
.
The thing is, you don't need to create such a type. Aliasing is not spatial but temporal. You can have multiple *mut T
pointing to the same place and it doesn't matter until you try to access one. This essentially converts it to a reference and the aliasing requirements need to be upheld while that reference is around.
raw pointers fall outside of Rust's safe memory model.
— The Rustonomicon
Different from references and smart pointers, raw pointers:
- Are allowed to ignore the borrowing rules by having both immutable and mutable pointers or multiple mutable pointers to the same location
- Aren’t guaranteed to point to valid memory
- Are allowed to be null
- Don’t implement any automatic cleanup
¸— The Rust Programming Language
See also:
1 You technically can, but that's only because of an implementation and backwards compatibility limitation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With