miri/shims/native_lib/
ffi.rs

1//! Support code for dealing with libffi.
2
3use libffi::low::CodePtr;
4use libffi::middle::{Arg as ArgPtr, Cif, Type as FfiType};
5
6/// Perform the actual FFI call.
7///
8/// # Safety
9///
10/// The safety invariants of the foreign function being called must be upheld (if any).
11pub unsafe fn call<R: libffi::high::CType>(fun: CodePtr, args: &mut [OwnedArg]) -> R {
12    let cif = Cif::new(args.iter_mut().map(|arg| arg.ty.take().unwrap()), R::reify().into_middle());
13    let arg_ptrs: Vec<_> = args.iter().map(|arg| ArgPtr::new(&*arg.bytes)).collect();
14    // SAFETY: Caller upholds that the function is safe to call.
15    unsafe { cif.call(fun, &arg_ptrs) }
16}
17
18/// An argument for an FFI call.
19#[derive(Debug, Clone)]
20pub struct OwnedArg {
21    /// The type descriptor for this argument.
22    ty: Option<FfiType>,
23    /// Corresponding bytes for the value.
24    bytes: Box<[u8]>,
25}
26
27impl OwnedArg {
28    /// Instantiates an argument from a type descriptor and bytes.
29    pub fn new(ty: FfiType, bytes: Box<[u8]>) -> Self {
30        Self { ty: Some(ty), bytes }
31    }
32}