pointersrustffierlang-nif

Raw pointer type for interior mutable struct


I’m doing some Rust FFI work for the Erlang NIF API, and I have these:

ErlNifEnv *enif_alloc_env();
void enif_free_env(ErlNifEnv* env);

This ErlNifEnv pointer gets passed to a variety of other functions but the user will never deref the pointer. Also, this pointer is not threadsafe (use amongst multiple threads would require a mutex). The naive Rust representation of this type would be..

struct ErlNifEnv;
*mut ErlNifEnv;

But, I think I can treat this type as having “interior mutability” which would lead to…

struct ErlNifEnv;
*const ErlNifEnv;

Should I be treating this pointer as const even though the underlying C code sees it as non-const?


Solution

  • I personally think that you should treat them as you treat references in Rust itself. When a function requires &mut reference, it is very likely that it will actually change the value, and if it requires &, then it is natural to expect that the value won't be changed (of course, disregarding inner mutability).

    C does not have a distinction between inherited and inner mutability, and so you can choose what to use *mut or *const solely based on how C functions work with this value. In fact, in properly written C API this distinction will be present in form of const qualifiers. Consequently, if there are any functions which want to mutate the value, go with *mut. If there are no such functions (e.g. this is an immutable structure which is created only once) go with *const. This is, of course, applies to the type you want to store in your wrapper - in FFI function signatures you should always mirror C API signatures.