Idiomatic Rust types in FFI signatures?
That was the main objective when creating and using ::safer_ffi:
Why go through the dangerously unsafe hassle of:
-
using
ptr: *const/mut T, len: usizepairs when wanting to use slices? -
using
*const c_charand*mut c_charandCStr / CString / Stringdances when wanting to use strings? -
losing all kind of ownership-borrow information with signatures such as:
// Is this taking ownership of `Foo` or "just" mutating it? #[no_mangle] pub unsafe extern "C" fn foo_stuff (foo: *mut Foo) { /* ... */ }
Can't we use our good ol' idiomatic
&/&mut/Boxtrinity types? And some equivalent to[_]slices,Vecs andStrings? And quid of closure types?
To which the answer is yes! All these types can be FFI-compatible,
provided they have a defined C layout. And this is precisely what safer_ffi does:
safer_ffidefines a bunch of idiomatic Rust types with a defined#[repr(C)]layout, to get both FFI compatibility and non-unsafeergonomics.
That is, for any type T that has a defined C layout, i.e., that is
ReprC (and Sized):
-
&'_ Tand&'_ mut Tare themselvesReprC!-
Same goes for
repr_c::Box<T>. -
They all have the C layout of a (non-nullable) raw pointer.
-
And all three support being
Option-wrapped (the layout remains that of a (now nullable) raw pointer, thanks to the enum layout optimization)
-
-
c_slice::Ref<'_, T>andc_slice::Mut<'_, T>are alsoReprCequivalents of&'_ [T]and&'_ mut [T].-
Same goes for
c_slice::Box<T>(to representBox<[T]>). -
They all have the C layout of a
structwith a.ptr,.lenpair of fields (where.ptris non-nullable). -
And all three support being
Option-wrapped too.-
In that case, the
.ptrfield becomes nullable; -
when it is
NULL, the.lenfield can be uninitialized: ⚠️ it is thus then UB to read the.lenfield ⚠️ (type safety and encapsulation ensure this UB cannot be triggered from within Rust; only the encapsulation-deprived C side can do that).
-
-
-
There is
repr_c::Vec<T>as well (extra.capacityfield w.r.t. generalization toc_slice::Box<T>), -
as well as
repr_c::String!-
with the slice versions (
.capacity-stripped) too:str::Boxandstr::Ref<'_>(Box<str>and&'_ strrespectively). -
although these definitions are capable of representing any sequence of UTF-8 encoded strings (thus supporting NULL bytes), since the C world is not really capable of handling those (except as opaque blobs of bytes),
char *-compatible null-terminated UTF-8 string types are available as well:-
char_p::Ref<'_>forchar const *: a temporary borrow of such string (useful as input parameter). -
char_p::Boxforchar *: a pointer owning aBox-allocated such string (useful to return strings).
-
-