I would like to store the pointer to a rust struct inside of it's member C struct. Is it required that the struct be enclosed in a Rc rather than a Box?
The reason I'm asking is because although there is shared ownership here, the pointer is only ever accessed from within unsafe member functions of the Rust struct and the C struct's lifetime is tied to that of the enclosing Rust struct.
Here's an example ->
// C struct with constructor/destructor
struct c_foo {
void* internal; // pointer to rust `struct`
/* ... */
};
struct c_foo* c_foo_new();
void c_foo_free(struct c_foo* foo);
// FFI struct generated by bindgen
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Foo {
pub internal: *mut libc::c_void, // pointer to rust `struct`
/* ... */
}
// Rust struct that wraps the FFI struct
struct Bar {
ptr: *mut Foo, // private
/* ... */
}
impl Bar {
fn new() -> Box<Bar> {
unsafe {
let mut bar = Box::new(Bar { ptr: c_foo_new() });
let bar_ptr: *mut ffi::c_void = &mut bar as *mut _ as *mut ffi::c_void;
(*bar.ptr).internal = bar_ptr;
bar
}
}
}
impl Drop for Bar {
fn drop(&mut self) {
unsafe {
c_foo_free((*bar.ptr).internal);
}
}
}
So there's a C struct c_foo with a void * that stores a reference to the Rust struct Bar. Foo is just the bindgen generated Rust wrapper for c_foo.
Do I need a Box or Rc in the Bar::new() function?
To clarify, there is no shared ownership on the Rust side. There is shared ownership b/w the Rust and C side so I guess there is no benefit in using a Rc type.
BoxorRc. General guidance would be here, but why is it needed in the first place? You are already holding a pointer to a C struct. Does it have to be contained in another smart pointer? Moreover, the functionBar::newdoes not compile as it is. - E_net4Box<Bar>, whereas this version ofBar::newreturns just aBar. - E_net4Rconly if you need shared ownership in Rust code. Since C does not retain the semantics of this pointer type, C code needs to handle boundaries manually regardless. - E_net4Bar::newshould indeed returnBox<Bar>. But I think what you said in your next comment makes a lot of sense. That is what I was getting at when I wrote in the question that '... although there is shared ownership...'. So I guess I might as well handle it manually and just use a Box type. Your commentuse Rc only if you need shared ownership in Rust code.clears my confusion. Thanks! - Shoaib Ahmed