1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
use std::any::Any; use super::types::Type; /// Provides a builder-style API for constructing CIFs and closures. /// /// To use a builder, first construct it using [`Builder::new`](#method.new). /// The default calling convention is `ffi_abi_FFI_DEFAULT_ABI`, and the default /// function type is `extern "C" fn()` (or in C, `void(*)()`). Add /// argument types to the function type with the [`arg`](#method.arg) /// and [`args`](#method.args) methods. Set the result type with /// [`res`](#method.res). Change the calling convention, if necessary, /// with [`abi`](#method.abi). /// /// Once the builder is configured, construct a `Cif` with /// [`into_cif`](#method.into_cif) or a closure with /// [`into_closure`](#method.into_closure), /// [`into_closure_mut`](#method.into_closure_mut), or /// [`into_closure_once`](#method.into_closure_once). /// /// # Examples /// /// ``` /// use std::mem; /// use std::os::raw::c_void; /// /// use libffi::middle::*; /// use libffi::low; /// /// unsafe extern "C" fn lambda_callback<F: Fn(u64, u64) -> u64>( /// _cif: &low::ffi_cif, /// result: &mut u64, /// args: *const *const c_void, /// userdata: &F) /// { /// let args: *const &u64 = mem::transmute(args); /// let arg1 = **args.offset(0); /// let arg2 = **args.offset(1); /// /// *result = userdata(arg1, arg2); /// } /// /// let lambda = |x: u64, y: u64| x + y; /// /// let closure = Builder::new() /// .arg(Type::u64()) /// .arg(Type::u64()) /// .res(Type::u64()) /// .into_closure(lambda_callback, &lambda); /// /// unsafe { /// let fun: &unsafe extern "C" fn(u64, u64) -> u64 /// = mem::transmute(closure.code_ptr()); /// /// assert_eq!(11, fun(5, 6)); /// assert_eq!(12, fun(5, 7)); /// } /// ``` #[derive(Clone, Debug)] pub struct Builder { args: Vec<Type>, res: Type, abi: super::FfiAbi, } impl Default for Builder { fn default() -> Self { Builder::new() } } impl Builder { /// Constructs a `Builder`. pub fn new() -> Self { Builder { args: vec![], res: Type::void(), abi: super::ffi_abi_FFI_DEFAULT_ABI, } } /// Adds a type to the argument type list. pub fn arg(mut self, type_: Type) -> Self { self.args.push(type_); self } /// Adds several types to the argument type list. pub fn args<I>(mut self, types: I) -> Self where I: IntoIterator<Item=Type> { self.args.extend(types.into_iter()); self } /// Sets the result type. pub fn res(mut self, type_: Type) -> Self { self.res = type_; self } /// Sets the calling convention. pub fn abi(mut self, abi: super::FfiAbi) -> Self { self.abi = abi; self } /// Builds a CIF. pub fn into_cif(self) -> super::Cif { let mut result = super::Cif::new(self.args, self.res); result.set_abi(self.abi); result } /// Builds an immutable closure. /// /// # Arguments /// /// - `callback` — the function to call when the closure is invoked /// - `userdata` — the pointer to pass to `callback` along with the /// arguments when the closure is called /// /// # Result /// /// The new closure. pub fn into_closure<U, R>( self, callback: super::Callback<U, R>, userdata: &U) -> super::Closure { super::Closure::new(self.into_cif(), callback, userdata) } /// Builds a mutable closure. /// /// # Arguments /// /// - `callback` — the function to call when the closure is invoked /// - `userdata` — the pointer to pass to `callback` along with the /// arguments when the closure is called /// /// # Result /// /// The new closure. pub fn into_closure_mut<U, R>( self, callback: super::CallbackMut<U, R>, userdata: &mut U) -> super::Closure { super::Closure::new_mut(self.into_cif(), callback, userdata) } /// Builds a one-shot closure. /// /// # Arguments /// /// - `callback` — the function to call when the closure is invoked /// - `userdata` — the object to pass to `callback` along with the /// arguments when the closure is called /// /// # Result /// /// The new closure. pub fn into_closure_once<U: Any, R>( self, callback: super::CallbackOnce<U, R>, userdata: U) -> super::ClosureOnce { super::ClosureOnce::new(self.into_cif(), callback, userdata) } }