Expand description
Provides wrappers around closures which allows them to be called through context-free unsafe bare functions.
Context-free bare functions are not needed very often, as properly designed C APIs typically allow the user to specify an opaque pointer to a context object which will be provided to the function pointer. However, this is not always the case, and may be impossible in less common scenarios, e.g. function hooking for game modding/hacking.
§Features
The crate comes with the following feature flags:
no_std: Makes the crate compatible with#![no_std]. A dependency onallocandspinis still required.bundled_jit_alloc: Provides a global JIT allocator through thejit-allocatorcrate. This is enabled by default.proc_macros: Provides thecc::hrtbproc macro which is necessary for creating bare functions with signatures that involve higher-kinded lifetimes (i.e.for<'a, ...>statements), as well as thebare_dynproc macro for writingBareFn*types of boxed closures (i.e.Box<dyn Fn()>) more concisely.full: Enables all features except forno_std.
§Examples
Passing a closure to a C API taking a contextless function pointer:
use closure_ffi::{cc, BareFnMut};
// Imagine we have an foreign C API for reigstering and unregistering some callback function.
// Notably, the API does not let the user provide a context object to the callback.
unsafe extern "C" fn ffi_register_callback(cb: unsafe extern "C" fn(u32)) {
// ...
}
unsafe extern "C" fn ffi_unregister_callback(cb: unsafe extern "C" fn(u32)) {
// ...
}
#[cfg(feature = "bundled_jit_alloc")]
{
// We want to keep track of sum of callback arguments without using
// statics. This is where closure-ffi comes in:
let mut sum = 0; // Non-'static closures work too!
let wrapped = BareFnMut::new(cc::C, |x: u32| {
sum += x;
});
// Safety: Here, we assert that the foreign API won't use the callback
// in ways that break Rust's safety rules. Namely:
// - The exclusivity of the FnMut's borrow is respected.
// - If the calls are made from a different thread, the closure is Sync.
// - We unregister the callback before the BareFnMut is dropped.
unsafe {
ffi_register_callback(wrapped.bare());
// Do something that triggers the callback...
ffi_unregister_callback(wrapped.bare());
}
drop(wrapped);
println!("{sum}");
}Modules§
- bare_
closure - Provides the
BareFnOnce,BareFnMutandBareFnwrapper types which allow closures to be called through context-free unsafe bare functions. - cc
- Defines calling convention marker types for use with
BareFnvariants. - jit_
alloc - Abstractions around allocators that provide dual-mapped memory with XOR protection rules (one RW view and one RX view) suitable for emitting code at runtime.
- prelude
- Common imports required to use
closure-ffi.
Macros§
- bare_
dyn proc_macros - Shorthand for a
BareFn*type taking a boxed closure.
Structs§
- BareFn
- Wrapper around a
Fnclosure which exposes a bare function thunk that can invoke it without additional arguments. - Bare
FnMut - Wrapper around a
FnMutclosure which exposes a bare function thunk that can invoke it without additional arguments. - Bare
FnOnce - Wrapper around a
FnOnceclosure which exposes a bare function thunk that can invoke it without additional arguments. - JitAlloc
Error - Anonymous error that may be returned by
JitAllocimplementations whenJitAlloc::allocorJitAlloc::releasefail.
Traits§
- JitAlloc
- Generic allocator providing virtual memory suitable for emitting code at runtime.