libffi 0.5.3

Rust bindings for libffi
Documentation
//! A low-level wrapping of libffi, this layer makes no attempts at safety,
//! but tries to provide a somewhat more idiomatic interface.
//!
//! This module also re-exports types and constants necessary for using the
//! library, so it should not be generally necessary to use the `raw` module.
//! While this is a bit “Rustier” than [`raw`](../raw/index.html), I’ve
//! avoided drastic renaming in favor of hewing close to the libffi API.
//! See [`middle`](../middle/index.html) for an easier-to-use approach.

use std::mem;
use std::os::raw::{c_void, c_uint};

use raw;

/// The two kinds of errors reported by libffi.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Error {
    /// Given a bad or unsupported type representation.
    Typedef,
    /// Given a bad or unsupported ABI.
    Abi,
}

/// The `Result` type specialized for libffi `Error`s.
pub type Result<T> = ::std::result::Result<T, Error>;

// Converts the raw status type to a `Result`.
fn status_to_result<R>(status: raw::ffi_status, good: R) -> Result<R> {
    use raw::ffi_status::*;
    match status {
        FFI_OK => Ok(good),
        FFI_BAD_TYPEDEF => Err(Error::Typedef),
        FFI_BAD_ABI => Err(Error::Abi),
    }
}

/// Wraps a function pointer of unknown type.
///
/// This is used to make the API a bit easier to understand, and as a
/// simple type lint. As a `repr(C)` struct of one element, it should
/// be safe to transmute between `CodePtr` and `*mut c_void`, or between
/// collections thereof.
#[derive(Clone, Copy, Debug, Hash)]
#[repr(C)]
pub struct CodePtr(pub *mut c_void);

// How useful is this type? Does it need all the methods?
impl CodePtr {
    /// Initializes a code pointer from a function pointer.
    ///
    /// This is useful mainly for talking to C APIs that take untyped
    /// callbacks specified in the API as having type `void(*)()`.
    pub fn from_fun(fun: unsafe extern "C" fn()) -> Self {
        CodePtr(fun as *mut c_void)
    }

    /// Initializes a code pointer from a void pointer.
    ///
    /// This is the other common type used in APIs (or at least in
    /// libffi) for untyped callback arguments.
    pub fn from_ptr(fun: *const c_void) -> Self {
        CodePtr(fun as *mut c_void)
    }

    /// Gets the code pointer typed as a C function pointer.
    ///
    /// This is useful mainly for talking to C APIs that take untyped
    /// callbacks specified in the API as having type `void(*)()`.
    ///
    /// # Safety
    ///
    /// There is no checking that the returned type reflects the actual
    /// parameter and return types of the function. Unless the C
    /// function actually has type `void(*)()`, it will need to be
    /// cast before it is called.
    pub fn as_fun(&self) -> &unsafe extern "C" fn() {
        unsafe {
            mem::transmute::<&*mut c_void, &unsafe extern "C" fn()>(&self.0)
        }
    }

    /// Gets the code pointer typed as a “safe” C function pointer.
    ///
    /// This is useful mainly for talking to C APIs that take untyped
    /// callbacks specified in the API as having type `void(*)()`.
    ///
    /// # Safety
    ///
    /// There isn’t necessarily anything actually safe about the resulting
    /// function pointer—it’s up to the caller to know what they’re
    /// doing within the unsafety boundary, or undefined behavior may
    /// result. In particular,
    /// there is no checking that the returned type reflects the actual
    /// parameter and return types of the function. Unless the C
    /// function actually has type `void(*)()`, it will need to be
    /// cast before it is called.
    pub unsafe fn as_safe_fun(&self) -> &extern "C" fn() {
        mem::transmute::<&*mut c_void, &extern "C" fn()>(&self.0)
    }

    /// Gets the code pointer typed as a `const void*`.
    ///
    /// This is the other common type used in APIs (or at least in
    /// libffi) for untyped callback arguments.
    pub fn as_ptr(&self) -> *const c_void {
        self.0
    }

    /// Gets the code pointer typed as a `void*`.
    ///
    /// This is the other common type used in APIs (or at least in
    /// libffi) for untyped callback arguments.
    pub fn as_mut_ptr(&self) -> *mut c_void {
        self.0
    }
}

pub use raw::{ffi_abi, ffi_abi_FFI_DEFAULT_ABI, _ffi_type as ffi_type, ffi_status,
              ffi_cif, ffi_closure};

/// Re-exports the `ffi_type` objects used to describe the types of
/// arguments and results.
///
/// These are from [`raw`](../../raw/index.html), but are renamed by
/// removing the `ffi_type_` prefix. For example, `raw::ffi_type_void`
/// becomes `low::types::void`.
pub mod types {
    pub use raw::{ffi_type_void as void,
                  ffi_type_uint8 as uint8,
                  ffi_type_sint8 as sint8,
                  ffi_type_uint16 as uint16,
                  ffi_type_sint16 as sint16,
                  ffi_type_uint32 as uint32,
                  ffi_type_sint32 as sint32,
                  ffi_type_uint64 as uint64,
                  ffi_type_sint64 as sint64,
                  ffi_type_float as float,
                  ffi_type_double as double,
                  ffi_type_pointer as pointer,
                  ffi_type_longdouble as longdouble};
    #[cfg(feature = "complex")]
    pub use raw::{ffi_type_complex_float as complex_float,
                  ffi_type_complex_double as complex_double,
                  ffi_type_complex_longdouble as complex_longdouble};
}

/// Type tags used in constructing and inspecting `ffi_type`s.
///
/// For atomic types this tag doesn’t matter because libffi predeclares
/// [an instance of each one](types/index.html). However, for composite
/// types (structs and complex numbers), we need to create a new
/// instance of the `ffi_type` struct. In particular, the `type_` field
/// contains a value that indicates what kind of type is represented,
/// and we use these values to indicate that that we are describing a
/// struct or complex type.
///
/// # Examples
///
/// Suppose we have the following C struct:
///
/// ```c
/// struct my_struct {
///     uint16_t f1;
///     uint64_t f2;
/// };
/// ```
///
/// To pass it by value to a C function we can construct an
/// `ffi_type` as follows using `type_tag::STRUCT`:
///
/// ```
/// use std::ptr;
/// use libffi::low::{ffi_type, types, type_tag};
///
/// let mut elements = unsafe {
///     [ &mut types::uint16,
///       &mut types::uint64,
///       ptr::null_mut::<ffi_type>() ]
/// };
///
/// let mut my_struct: ffi_type = Default::default();
/// my_struct.type_ = type_tag::STRUCT;
/// my_struct.elements = elements.as_mut_ptr();
/// ```
pub mod type_tag {
    use raw;
    use std::os::raw::c_ushort;

    /// Indicates a structure type.
    pub const STRUCT:  c_ushort = raw::ffi_type_enum::STRUCT as c_ushort;

    /// Indicates a complex number type.
    ///
    /// This item is enabled by `#[cfg(feature = "complex")]`.
    #[cfg(feature = "complex")]
    pub const COMPLEX: c_ushort = raw::ffi_type_enum::COMPLEX as c_ushort;
}

/// Initalizes a CIF (Call Interface) with the given ABI
/// and types.
///
/// We need to initialize a CIF before we can use it to call a function
/// or create a closure. This function lets us specify the calling
/// convention to use and the argument and result types. For varargs
/// CIF initialization, see [`prep_cif_var`](fn.prep_cif_var.html).
///
///
/// # Safety
///
/// The CIF `cif` retains references to `rtype` and `atypes`, so if
/// they are no longer live when the CIF is used then the behavior is
/// undefined.
///
/// # Arguments
///
/// - `cif` — the CIF to initialize
/// - `abi` — the calling convention to use
/// - `nargs` — the number of arguments
/// - `rtype` — the result type
/// - `atypes` — the argument types (length must be at least `nargs`)
///
/// # Result
///
/// `Ok(())` for success or `Err(e)` for failure.
///
/// # Examples
///
/// ```
/// use libffi::low::*;
///
/// let mut args: [*mut ffi_type; 2] = unsafe {
///     [ &mut types::sint32,
///       &mut types::uint64 ]
/// };
/// let mut cif: ffi_cif = Default::default();
///
/// unsafe {
///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 2,
///              &mut types::pointer, args.as_mut_ptr())
/// }.unwrap();
/// ```
pub unsafe fn prep_cif(cif: *mut ffi_cif,
                       abi: ffi_abi,
                       nargs: usize,
                       rtype: *mut ffi_type,
                       atypes: *mut *mut ffi_type)
                       -> Result<()>
{
    let status = raw::ffi_prep_cif(cif, abi,
                                 nargs as c_uint,
                                 rtype, atypes);
    status_to_result(status, ())
}

/// Initalizes a CIF (Call Interface) for a varargs function.
///
/// We need to initialize a CIF before we can use it to call a function
/// or create a closure. This function lets us specify the calling
/// convention to use and the argument and result types. For non-varargs
/// CIF initialization, see [`prep_cif`](fn.prep_cif.html).
///
/// # Safety
///
/// The CIF `cif` retains references to `rtype` and `atypes`, so if
/// they are no longer live when the CIF is used then the behavior is
/// undefined.
///
/// # Arguments
///
/// - `cif` — the CIF to initialize
/// - `abi` — the calling convention to use
/// - `nfixedargs` — the number of fixed arguments
/// - `ntotalargs` — the total number of arguments, including fixed and
///    var args
/// - `rtype` — the result type
/// - `atypes` — the argument types (length must be at least `nargs`)
///
/// # Result
///
/// `Ok(())` for success or `Err(e)` for failure.
///
pub unsafe fn prep_cif_var(cif: *mut ffi_cif,
                           abi: ffi_abi,
                           nfixedargs: usize,
                           ntotalargs: usize,
                           rtype: *mut ffi_type,
                           atypes: *mut *mut ffi_type)
                           -> Result<()>
{
    let status = raw::ffi_prep_cif_var(cif, abi,
                                     nfixedargs as c_uint,
                                     ntotalargs as c_uint,
                                     rtype, atypes);
    status_to_result(status, ())
}

/// Calls a C function as specified by a CIF.
///
/// # Arguments
///
/// * `cif` — describes the argument and result types and the calling
///           convention
/// * `fun` — the function to call
/// * `args` — the arguments to pass to `fun`
///
/// # Result
///
/// The result of calling `fun` with `args`.
///
/// # Examples
///
/// ```
/// use std::os::raw::c_void;
/// use libffi::low::*;
///
/// extern "C" fn c_function(a: u64, b: u64) -> u64 { a + b }
///
/// let result = unsafe {
///     let mut args: Vec<*mut ffi_type> = vec![ &mut types::uint64,
///                                              &mut types::uint64 ];
///     let mut cif: ffi_cif = Default::default();
///
///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 2,
///              &mut types::uint64, args.as_mut_ptr()).unwrap();
///
///     call(&mut cif, CodePtr(c_function as *mut _),
///          vec![ &mut 4u64 as *mut _ as *mut c_void,
///                &mut 5u64 as *mut _ as *mut c_void ].as_mut_ptr())
/// };
///
/// assert_eq!(9, result);
/// ```
pub unsafe fn call<R>(cif:  *mut ffi_cif,
                      fun:  CodePtr,
                      args: *mut *mut c_void) -> R
{
    let mut result: R = mem::uninitialized();
    raw::ffi_call(cif,
                  Some(*fun.as_safe_fun()),
                  &mut result as *mut R as *mut c_void,
                  args);
    result
}

/// Allocates a closure.
///
/// Returns a pair of the writable closure object and the function
/// pointer for calling it. The former acts as a handle to the closure,
/// and is used to configure and free it. The latter is the code pointer
/// used to invoke the closure. Before it can be invoked, it must be
/// initialized with [`prep_closure`](fn.prep_closure.html) and
/// [`prep_closure_mut`](fn.prep_closure_mut.html). The closure must be
/// deallocated using [`closure_free`](fn.closure_free.html), after
/// which point the code pointer should not be used.
///
/// # Examples
///
/// ```
/// use libffi::low::*;
///
/// let (closure_handle, code_ptr) = closure_alloc();
/// ```
pub fn closure_alloc() -> (*mut ffi_closure, CodePtr) {
    unsafe {
        let mut code_pointer: *mut c_void = mem::uninitialized();
        let closure = raw::ffi_closure_alloc(mem::size_of::<ffi_closure>(),
                                             &mut code_pointer);
        (closure as *mut ffi_closure, CodePtr::from_ptr(code_pointer))
    }
}

/// Frees a closure.
///
/// Closures allocated with [`closure_alloc`](fn.closure_alloc.html)
/// must be deallocated with `closure_free`.
///
/// # Examples
///
/// ```
/// use libffi::low::*;
///
/// let (closure_handle, code_ptr) = closure_alloc();
///
/// // ...
///
/// unsafe {
///     closure_free(closure_handle);
/// }
/// ```
pub unsafe fn closure_free(closure: *mut ffi_closure) {
    raw::ffi_closure_free(closure as *mut c_void);
}

/// The type of function called by a closure.
///
/// `U` is the type of the user data captured by the closure and passed
/// to the callback, and `R` is the type of the result. The parameters
/// are not typed, since they are passed as a C array of `void*`.
pub type Callback<U, R>
    = unsafe extern "C" fn(cif:      &ffi_cif,
                           result:   &mut R,
                           args:     *const *const c_void,
                           userdata: &U);

/// The type of function called by a mutable closure.
///
/// `U` is the type of the user data captured by the closure and passed
/// to the callback, and `R` is the type of the result. The parameters
/// are not typed, since they are passed as a C array of `void*`.
pub type CallbackMut<U, R>
    = unsafe extern "C" fn(cif:      &ffi_cif,
                           result:   &mut R,
                           args:     *const *const c_void,
                           userdata: &mut U);

/// The callback type expected by `raw::ffi_prep_closure_loc`.
pub type RawCallback
    = unsafe extern "C" fn(cif:      *mut ffi_cif,
                           result:   *mut c_void,
                           args:     *mut *mut c_void,
                           userdata: *mut c_void);

/// Initializes a closure with a callback function and userdata.
///
/// After allocating a closure with
/// [`closure_alloc`](fn.closure_alloc.html), it needs to be initialized
/// with a function `callback` to call and a pointer `userdata` to pass
/// to it. Invoking the closure’s code pointer will then pass the provided
/// arguments and the user data pointer to the callback.
///
/// For mutable userdata use [`prep_closure_mut`](fn.prep_closure_mut.html).
///
/// # Safety
///
/// The closure retains a reference to CIF `cif`, so that must
/// still be live when the closure is used lest undefined behavior
/// result.
///
/// # Arguments
///
/// - `closure` — the closure to initialize
/// - `cif` — the calling convention and types for calling the closure
/// - `callback` — the function that the closure will invoke
/// - `userdata` — the closed-over value, stored in the closure and
///    passed to the callback upon invocation
/// - `code` — the closure’s code pointer, *i.e.*, the second component
///   returned by [`closure_alloc`](fn.closure_alloc.html).
///
/// # Result
///
/// `Ok(())` for success or `Err(e)` for failure.
///
/// # Examples
///
/// ```
/// use libffi::low::*;
///
/// use std::mem;
/// use std::os::raw::c_void;
///
/// unsafe extern "C" fn callback(_cif: &ffi_cif,
///                               result: &mut u64,
///                               args: *const *const c_void,
///                               userdata: &u64)
/// {
///     let args: *const &u64 = mem::transmute(args);
///     *result = **args + *userdata;
/// }
///
/// fn twice(f: extern "C" fn(u64) -> u64, x: u64) -> u64 {
///     f(f(x))
/// }
///
/// unsafe {
///     let mut cif: ffi_cif = Default::default();
///     let mut args = [&mut types::uint64 as *mut _];
///     let mut userdata: u64 = 5;
///
///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 1, &mut types::uint64,
///              args.as_mut_ptr()).unwrap();
///
///     let (closure, code) = closure_alloc();
///     let add5: extern "C" fn(u64) -> u64 = mem::transmute(code);
///
///     prep_closure(closure,
///                  &mut cif,
///                  callback,
///                  &mut userdata,
///                  CodePtr(add5 as *mut _)).unwrap();
///
///     assert_eq!(11, add5(6));
///     assert_eq!(12, add5(7));
///
///     assert_eq!(22, twice(add5, 12));
/// }
/// ```
pub unsafe fn prep_closure<U, R>(closure:  *mut ffi_closure,
                                 cif:      *mut ffi_cif,
                                 callback: Callback<U, R>,
                                 userdata: *const U,
                                 code:     CodePtr)
    -> Result<()>
{
    let status = raw::ffi_prep_closure_loc
        (closure,
         cif,
         Some(mem::transmute::<Callback<U, R>, RawCallback>(callback)),
         userdata as *mut c_void,
         code.as_mut_ptr());
    status_to_result(status, ())
}

/// Initializes a mutable closure with a callback function and (mutable)
/// userdata.
///
/// After allocating a closure with
/// [`closure_alloc`](fn.closure_alloc.html), it needs to be initialized
/// with a function `callback` to call and a pointer `userdata` to pass
/// to it. Invoking the closure’s code pointer will then pass the provided
/// arguments and the user data pointer to the callback.
///
/// For immutable userdata use [`prep_closure`](fn.prep_closure.html).
///
/// # Safety
///
/// The closure retains a reference to CIF `cif`, so that must
/// still be live when the closure is used lest undefined behavior
/// result.
///
/// # Arguments
///
/// - `closure` — the closure to initialize
/// - `cif` — the calling convention and types for calling the closure
/// - `callback` — the function that the closure will invoke
/// - `userdata` — the closed-over value, stored in the closure and
///    passed to the callback upon invocation
/// - `code` — the closure’s code pointer, *i.e.*, the second component
///   returned by [`closure_alloc`](fn.closure_alloc.html).
///
/// # Result
///
/// `Ok(())` for success or `Err(e)` for failure.
///
/// # Examples
///
/// ```
/// use libffi::low::*;
///
/// use std::mem;
/// use std::os::raw::c_void;
///
/// unsafe extern "C" fn callback(_cif: &ffi_cif,
///                               result: &mut u64,
///                               args: *const *const c_void,
///                               userdata: &mut u64)
/// {
///     let args: *const &u64 = mem::transmute(args);
///     *result = *userdata;
///     *userdata += **args;
/// }
///
/// fn twice(f: extern "C" fn(u64) -> u64, x: u64) -> u64 {
///     f(f(x))
/// }
///
/// unsafe {
///     let mut cif: ffi_cif = Default::default();
///     let mut args = [&mut types::uint64 as *mut _];
///     let mut userdata: u64 = 5;
///
///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 1, &mut types::uint64,
///              args.as_mut_ptr()).unwrap();
///
///     let (closure, code) = closure_alloc();
///     let add5: extern "C" fn(u64) -> u64 = mem::transmute(code);
///
///     prep_closure_mut(closure,
///                      &mut cif,
///                      callback,
///                      &mut userdata,
///                      CodePtr(add5 as *mut _)).unwrap();
///
///     assert_eq!(5, add5(6));
///     assert_eq!(11, add5(7));
///
///     assert_eq!(19, twice(add5, 1));
/// }
/// ```
pub unsafe fn prep_closure_mut<U, R>(closure:  *mut ffi_closure,
                                     cif:      *mut ffi_cif,
                                     callback: CallbackMut<U, R>,
                                     userdata: *mut U,
                                     code:     CodePtr)
    -> Result<()>
{
    let status = raw::ffi_prep_closure_loc
        (closure,
         cif,
         Some(mem::transmute::<CallbackMut<U, R>, RawCallback>(callback)),
         userdata as *mut c_void,
         code.as_mut_ptr());
    status_to_result(status, ())
}