c_strange_t
is an opaque C type that is only seen behind a pointer. When wrapping this type, there are times when it is our responsibility to free memory using c_free_strange_t(*c_strange_t)
, and other times when we are not responsible for freeing the data, we are only responsible for accurately controlling the lifetime.
It would be ergonomic if this type could be mapped into 2 types in Rust that work in a similar way to str
and String
, where there is impl Deref<Target=str> for String
. The borrowed type would need to be marked as only valid behind a reference.
Is this possible, and how would it be done?
This appears to work, but it does require using a small
unsafe
block, so you should test under the normal tools like Miri and Valgrind. The primary assumption made here1 is thatc_void
cannot be constructed normally.#[repr(transparent)]
is used to ensure that theFooBorrowed
newtype has the same memory layout as ac_void
. Everything should end up as "just a pointer":If the C library actually hands you a pointer, you would need to do some more
unsafe
:As you identified,
FooBorrowed::new
returns a reference with an unrestricted lifetime; this is pretty dangerous. In many cases, you can construct a smaller scope and use something that provides a lifetime:This prevents you from using the reference beyond when the pointer variable is valid, which is not guaranteed to be the true lifetime, but is "close enough" in many cases. It's more important to be too short and not too long!
1 — In future versions of Rust, you should use extern types to create a guaranteed opaque type: