Function libffi::low::prep_closure [] [src]

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<()>

Initializes a closure with a callback function and 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 mutable userdata use prep_closure_mut.

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