fiffi
fiffi ([fi`f:i]) provides Rust bindings for libffi. libffi-rs already provides Rust
bindings for libffi, but fiffi aims to provide more ergonomic bindings that makes it easier to
avoid safety issues when using functionality provided by libffi.
The crate uses libffi-sys-rs to build and link the underlying libffi library. fiffi is
no_std but requires alloc.
Use Cases
fiffi is built around three main use cases:
- Calling foreign functions whose signatures are not fully known at compile time with
Function. - Creating function pointers to Rust closures with
Closure. - Creating function pointers with arbitrary signatures chosen at run time backed by Rust callbacks
with
DynamicClosure.
Examples
Add fiffi to your Cargo.toml:
[]
= "0.1"
Calling an FFI function with Function
use ;
use Type;
// Typically when using fiffi, the function's signature is not known at compile-time. If you know
// the function signature at compile-time, it is probably preferable to call the function pointer
// directly instead of using an external library for it.
extern "C"
let function = new;
let a = 10i32;
let b = 32i32;
let mut result = 0i32;
// SAFETY: `function` was built from `add` with matching argument and return
// types, and `result` is valid storage for the return value.
unsafe
assert_eq!;
Converting a Rust closure to a function pointer with Closure
use Closure;
let offset = 5i32;
let add_offset = new;
// `add_offset.as_fn_ptr()` can now be used to retrieve an `extern "C"` function pointer to call the
// closure.
// SAFETY: `add_offset` accepts one `i32` argument, returns `i32`, and remains alive while the
// function pointer is used.
let add_offset_fn = unsafe ;
assert_eq!;
Creating a function pointer with a function signature defined at run time with DynamicClosure
use MaybeUninit;
use DynamicClosureCall;
use DynamicClosure;
use Type;
let add_offset = new;
// SAFETY: `add_offset` represents an `extern "C"` function that accepts one `i32` and returns an
// `i32`. `add_offset` remains alive while it is called.
let add_offset_fn = unsafe ;
assert_eq!;
Features
closure: includesClosureandDynamicClosurefunction-pointer support. This feature is enabled by default.check_only: forwardslibffi-sys'scheck_onlyfeature to speed upcargo checkby not compiling libffi.system: forwardslibffi-sys'ssystemfeature to dynamically link to a system libffi instead of compiling a static library. Note that some functionality may require libffi 3.5.0.
libffi-rs or fiffi?
See libffi-rs-2-fiffi.md for a comparison of how two simple code snippets using libffi-rs
would be written using fiffi.
Reasons to prefer libffi-rs
- Mature project with more than 1 maintainer
- Used by large projects such as
mirianddeno - Prioritizes stability and support for older Rust versions
- Several abstraction levels (
low,middle,high) for different needs
Reasons to prefer fiffi
- Smaller API with one way to do something rather than different abstraction levels
- Designed to not allow invalid function signatures or ABIs, which may cause
libffi-rsto return an error or panic
Supported targets
The targets below are tested in fiffi's CI tests. Additional targets may work, but are not tested
in CI; run the full test suite before using fiffi on another platform to ensure that everything
works as intended.
Development currently occurs mainly on x86_64 Linux and Windows.
aarch64-apple-darwinaarch64-pc-windows-gnullvmaarch64-pc-windows-msvcaarch64-unknown-linux-gnuarmv7-unknown-linux-gnueabihfi686-pc-windows-gnui686-pc-windows-msvci686-unknown-linux-gnuloongarch64-unknown-linux-gnupowerpc-unknown-linux-gnupowerpc64-unknown-linux-gnupowerpc64le-unknown-linux-gnuriscv64gc-unknown-linux-gnus390x-unknown-linux-gnusparc64-unknown-linux-gnux86_64-apple-darwinx86_64-pc-windows-gnux86_64-pc-windows-gnullvmx86_64-pc-windows-msvcx86_64-unknown-linux-gnux86_64-unknown-linux-musl