Rc
provides from_raw(), but RefCell
does not. Thus Rc<RefCell<T>>
can not be obtained from *const T
.
Is it good idea to provide RefCell::from_raw()
?
Rc
provides from_raw(), but RefCell
does not. Thus Rc<RefCell<T>>
can not be obtained from *const T
.
Is it good idea to provide RefCell::from_raw()
?
Two things:
T
, because the RefCell has some extra inline dataRc::from_raw
is only valid is only valid to call on pointers from Rc::into_raw
, so you can't call it on arbitrary pointersOk I forgot that Rc introduces one level of indirection.
However my purpose is to obtain Rc<RefCell<T>>
from *const T
and wonder if it is feasible.
If it's really *const T
type, then it's not possible at all, because both Rc
and RefCell
have a memory layout that is different from T
and are incompatible with it (T
has no room to store refcount and mutability flag).
If you've used Rc::into_raw
, then you can get it back from *const RefCell<T>
.
I see there's no non-hacky way to get a raw owning T
pointer from Rc<RefCell>
, because RefCell
doesn't expose its internal layout. So yeah, it would be nice to have a dedicated method for it.
Here's a workaround with a hacky pointer arithmetic:
let rcell = Rc::new(RefCell::new(123));
let cell_start = (&*rcell) as *const RefCell<_> as *const u8;
let tmp = rcell.borrow();
let data_start = (&*tmp) as *const i32 as *const u8;
drop(tmp);
let cell_offset = unsafe { data_start.offset_from(cell_start) };
let cell_raw = Rc::into_raw(rcell);
let data_raw = unsafe { (cell_raw as *mut u8).offset(cell_offset) as *mut i32 };
eprintln!("{}", unsafe { *data_raw });
unsafe { *data_raw = 456; }
let rc_raw = unsafe { (data_raw as *mut u8).offset(-cell_offset) as *mut RefCell<i32> };
let rc = unsafe { Rc::from_raw(rc_raw) };
eprintln!("{}", rc.borrow());
Seems exactly what I want.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.