A comprehensive library providing safe abstractions for Foreign Function
Interface (FFI) operations. The foreign crate offers traits to safely
convert between Rust types and their C representations, providing clarity
about which operations allocate memory and therefore the performance
characteristics.
Overview
When working with C libraries from Rust, different Rust types may
have different naming and conventions for converting to their
C representation and back. Even if you try to keep a common
convention for your own enums and structs, they still wouldn't
apply to standard library structs such as [String]/[str] and
CString/CStr.
This library provides a comprehensive set of traits and wrapper types that abstract the lifetime of the resulting pointers and that make these operations ergonomic.
The conversion traits themselves follow intuitive naming patterns that
clearly indicate their behavior and ownership implications. Rust terms
like clone or clone_from are used to show clearly where allocations
happen. [CloneToForeign] and [IntoForeign] convert Rust data to
C representations, respectively with a deep copy and by consuming the
Rust object; [FromForeign], [BorrowForeign] and [BorrowForeignMut]
convert C data back to Rust.
Likewise, the performance characteristics of each conversion are fixed;
optimized methods like borrow_foreign()
or into_foreign() are only available if
they can operate with no copying.
Usage examples
Rust → C Conversion
Copying:
let foreign = rust_value.clone_to_foreign();
call_c_function(foreign.as_ptr());
// Value freed automatically
Giving ownership to C:
let foreign_ptr = rust_value.clone_to_foreign_ptr();
call_c_function(foreign_ptr);
Consuming:
// rust_value is typically heap-allocated, e.g. a Box, String or Vec
let foreign = rust_value.into_foreign();
call_c_function(foreign.as_ptr());
// Value freed automatically
Borrowing for temporary use:
let rust_data = get_some_data();
let borrowed = rust_data.borrow_foreign();
call_c_function(borrowed.as_ptr());
C → Rust Conversion
Copying:
let rust_value = unsafe { RustType::cloned_from_foreign(c_ptr) };
Copying and freeing the C version:
let rust_value = unsafe { RustType::from_foreign(c_ptr) };
let rust_value: RustType = unsafe { c_ptr.into_native() };
Comparison to glib-rs
glib-rs provides a similar set of traits. A rough comparison is as follows:
glib-rs |
foreign-rs |
|---|---|
from_glib_full() |
from_foreign() |
from_glib_none() |
cloned_from_foreign() |
to_glib_full() |
clone_to_foreign_ptr() |
to_glib_none() |
clone_to_foreign() |