(Sorry if it's a stupid question, I'm fairly new to Rust)
I'm working with a Rust binding to a C library, and I'm not sure if it's implemented correctly. This library is gccjit
, but I think it will be more educative if I express it as a general problem.
The C library is a collection of functions and data types. Some functions are used to create an instance, these return "owning pointer"; some functions are used to mutate those data structures, they take this pointer. I would normally design the binding as follows:
struct TheType {
// the pointer to the corresponding C type
ptr: *mut c_void,
}
impl TheType {
fn new() -> Self { /*...*/ }
// Has to be mut because the underlying C function mutates the structure
fn set_some_property(&mut self, data: Data) {
unsafe { (c_set_function(self.ptr)) }
}
// Doesn't have to be mut because the underlying C function does not mutate the structure
fn get_something(&self) -> Something {
unsafe { (c_get_function(self.ptr)).into() }
}
}
Due to the way this library is used, I would like to have all methods take &self
to avoid fighting the borrow checker. (This is how this library is implemented now. I suspect it's unsound).
My questions are:
- Is my suspicion that
&self
methods that lead to logically mutating the contents are unsound? - If yes, would wrapping the
ptr
field inCell
fix the issue?
N.B: the library is inherently single-threaded and I don't care whether the Rust binding types are thread safe or not.