Function libffi::low::prep_closure_mut

source ·
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<()>
Expand description

Initializes a mutable closure with a callback function and (mutable) userdata.

After allocating a closure with closure_alloc, 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.

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.

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));
}