I’m trying to wrap a C-api into Rust. It’s an astronomy data format library cfitsio.
Encapsulating the file state is a fitsfile
struct, which is managed by the open and close functions:
fitsfile *fptr; // struct holding file position etc.
int status = 0; // how errors are reported
// Open a file on disk
fits_open_file(&fptr, "filename.fits", READONLY, &status);
// Close the file
fits_close_file(fptr, &status);
The fits_open_file
function allocates the memory, and sets the given pointer to the allocated memory. I have started to wrap this pointer object, but want to use Rust’s borrowing semantics to manage mutability of this state object, hopefully allowing concurrent file access (which is not supported in the C-api).
My WIP wrapper library wraps this fitsfile
into a rustier FitsFile
(source) object, and stores a *const fitsfile
member. It’s const
because the pointer itself does not change. My issue is that the memory it points to does change.
Currently using the FitsFile
object does not require it to be defined as mut
which is mis-representing how the library works.
What I’d like to do is store the fitsfile
object itself. It’s not defined as Copy
so move semantics should be in play, but Rust does not allow moving from dereferenced raw pointers.
One reasonable alternative is to ensure that any methods added to this struct (or other relevant state structs) accept &mut self
. Is this typically done in ffi code?
Yet another alternative is to design an API that does not reflect the C api, but is more typical of Rust APIs, but this needs more thought. I partly feel that the end user should not need to worry about the in-memory representation of the file state changing, but only when the user wants to change the file. I may consider a further high level API wrapping the current one which is more user-friendly.
This is my first serious Rust project, and I’d be interested to hear any comments.