| 1 | //! A low-level wrapping of libffi, this layer makes no attempts at safety, | 
| 2 | //! but tries to provide a somewhat more idiomatic interface. | 
|---|
| 3 | //! | 
|---|
| 4 | //! This module also re-exports types and constants necessary for using the | 
|---|
| 5 | //! library, so it should not be generally necessary to use the `raw` module. | 
|---|
| 6 | //! While this is a bit “Rustier” than [`raw`](crate::raw), I’ve | 
|---|
| 7 | //! avoided drastic renaming in favor of hewing close to the libffi API. | 
|---|
| 8 | //! See [`middle`](crate::middle) for an easier-to-use approach. | 
|---|
| 9 |  | 
|---|
| 10 | use std::mem; | 
|---|
| 11 | use std::os::raw::{c_uint, c_void}; | 
|---|
| 12 |  | 
|---|
| 13 | use crate::raw; | 
|---|
| 14 |  | 
|---|
| 15 | /// The two kinds of errors reported by libffi. | 
|---|
| 16 | #[ derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] | 
|---|
| 17 | pub enum Error { | 
|---|
| 18 | /// Given a bad or unsupported type representation. | 
|---|
| 19 | Typedef, | 
|---|
| 20 | /// Given a bad or unsupported ABI. | 
|---|
| 21 | Abi, | 
|---|
| 22 | } | 
|---|
| 23 |  | 
|---|
| 24 | /// The [`std::result::Result`] type specialized for libffi [`Error`]s. | 
|---|
| 25 | pub type Result<T> = ::std::result::Result<T, Error>; | 
|---|
| 26 |  | 
|---|
| 27 | // Converts the raw status type to a `Result`. | 
|---|
| 28 | fn status_to_result<R>(status: raw::ffi_status, good: R) -> Result<R> { | 
|---|
| 29 | if status == raw::ffi_status_FFI_OK { | 
|---|
| 30 | Ok(good) | 
|---|
| 31 | } else if status == raw::ffi_status_FFI_BAD_TYPEDEF { | 
|---|
| 32 | Err(Error::Typedef) | 
|---|
| 33 | } | 
|---|
| 34 | // If we don't recognize the status, that is an ABI error: | 
|---|
| 35 | else { | 
|---|
| 36 | Err(Error::Abi) | 
|---|
| 37 | } | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 | /// Wraps a function pointer of unknown type. | 
|---|
| 41 | /// | 
|---|
| 42 | /// This is used to make the API a bit easier to understand, and as a | 
|---|
| 43 | /// simple type lint. As a `repr(C)` struct of one element, it should | 
|---|
| 44 | /// be safe to transmute between `CodePtr` and `*mut c_void`, or between | 
|---|
| 45 | /// collections thereof. | 
|---|
| 46 | #[ derive(Clone, Copy, Debug, Hash)] | 
|---|
| 47 | #[ repr(C)] | 
|---|
| 48 | pub struct CodePtr(pub *mut c_void); | 
|---|
| 49 |  | 
|---|
| 50 | // How useful is this type? Does it need all the methods? | 
|---|
| 51 | impl CodePtr { | 
|---|
| 52 | /// Initializes a code pointer from a function pointer. | 
|---|
| 53 | /// | 
|---|
| 54 | /// This is useful mainly for talking to C APIs that take untyped | 
|---|
| 55 | /// callbacks specified in the API as having type `void(*)()`. | 
|---|
| 56 | pub fn from_fun(fun: unsafe extern "C"fn()) -> Self { | 
|---|
| 57 | CodePtr(fun as *mut c_void) | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 | /// Initializes a code pointer from a void pointer. | 
|---|
| 61 | /// | 
|---|
| 62 | /// This is the other common type used in APIs (or at least in | 
|---|
| 63 | /// libffi) for untyped callback arguments. | 
|---|
| 64 | pub fn from_ptr(fun: *const c_void) -> Self { | 
|---|
| 65 | CodePtr(fun as *mut c_void) | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | /// Gets the code pointer typed as a C function pointer. | 
|---|
| 69 | /// | 
|---|
| 70 | /// This is useful mainly for talking to C APIs that take untyped | 
|---|
| 71 | /// callbacks specified in the API as having type `void(*)()`. | 
|---|
| 72 | /// | 
|---|
| 73 | /// # Safety | 
|---|
| 74 | /// | 
|---|
| 75 | /// There is no checking that the returned type reflects the actual | 
|---|
| 76 | /// parameter and return types of the function. Unless the C | 
|---|
| 77 | /// function actually has type `void(*)()`, it will need to be | 
|---|
| 78 | /// cast before it is called. | 
|---|
| 79 | pub fn as_fun(&self) -> &unsafe extern "C"fn() { | 
|---|
| 80 | unsafe { self.as_any_ref_() } | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | /// Gets the code pointer typed as a “safe” C function pointer. | 
|---|
| 84 | /// | 
|---|
| 85 | /// This is useful mainly for talking to C APIs that take untyped | 
|---|
| 86 | /// callbacks specified in the API as having type `void(*)()`. | 
|---|
| 87 | /// | 
|---|
| 88 | /// # Safety | 
|---|
| 89 | /// | 
|---|
| 90 | /// There isn’t necessarily anything actually safe about the resulting | 
|---|
| 91 | /// function pointer—it’s up to the caller to know what they’re | 
|---|
| 92 | /// doing within the unsafety boundary, or undefined behavior may | 
|---|
| 93 | /// result. In particular, | 
|---|
| 94 | /// there is no checking that the returned type reflects the actual | 
|---|
| 95 | /// parameter and return types of the function. Unless the C | 
|---|
| 96 | /// function actually has type `void(*)()`, it will need to be | 
|---|
| 97 | /// cast before it is called. | 
|---|
| 98 | pub unsafe fn as_safe_fun(&self) -> &extern "C"fn() { | 
|---|
| 99 | self.as_any_ref_() | 
|---|
| 100 | } | 
|---|
| 101 |  | 
|---|
| 102 | pub(crate) unsafe fn as_any_ref_<T>(&self) -> &T { | 
|---|
| 103 | &*(&self.0 as *const _ as *const T) | 
|---|
| 104 | } | 
|---|
| 105 |  | 
|---|
| 106 | /// Gets the code pointer typed as a `const void*`. | 
|---|
| 107 | /// | 
|---|
| 108 | /// This is the other common type used in APIs (or at least in | 
|---|
| 109 | /// libffi) for untyped callback arguments. | 
|---|
| 110 | pub fn as_ptr(self) -> *const c_void { | 
|---|
| 111 | self.0 | 
|---|
| 112 | } | 
|---|
| 113 |  | 
|---|
| 114 | /// Gets the code pointer typed as a `void*`. | 
|---|
| 115 | /// | 
|---|
| 116 | /// This is the other common type used in APIs (or at least in | 
|---|
| 117 | /// libffi) for untyped callback arguments. | 
|---|
| 118 | pub fn as_mut_ptr(self) -> *mut c_void { | 
|---|
| 119 | self.0 | 
|---|
| 120 | } | 
|---|
| 121 | } | 
|---|
| 122 |  | 
|---|
| 123 | pub use raw::{ | 
|---|
| 124 | ffi_abi, ffi_abi_FFI_DEFAULT_ABI, ffi_arg, ffi_cif, ffi_closure, ffi_sarg, ffi_status, ffi_type, | 
|---|
| 125 | }; | 
|---|
| 126 |  | 
|---|
| 127 | /// Re-exports the [`ffi_type`] objects used to describe the types of | 
|---|
| 128 | /// arguments and results. | 
|---|
| 129 | /// | 
|---|
| 130 | /// These are from [the raw layer](crate::raw), but are renamed by | 
|---|
| 131 | /// removing the `ffi_type_` prefix. For example, [`raw::ffi_type_void`] | 
|---|
| 132 | /// becomes [`types::void`]. | 
|---|
| 133 | pub mod types { | 
|---|
| 134 | pub use crate::raw::{ | 
|---|
| 135 | ffi_type_double as double, ffi_type_float as float, ffi_type_pointer as pointer, | 
|---|
| 136 | ffi_type_sint16 as sint16, ffi_type_sint32 as sint32, ffi_type_sint64 as sint64, | 
|---|
| 137 | ffi_type_sint8 as sint8, ffi_type_uint16 as uint16, ffi_type_uint32 as uint32, | 
|---|
| 138 | ffi_type_uint64 as uint64, ffi_type_uint8 as uint8, ffi_type_void as void, | 
|---|
| 139 | }; | 
|---|
| 140 |  | 
|---|
| 141 | #[ cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] | 
|---|
| 142 | pub use crate::raw::ffi_type_longdouble as longdouble; | 
|---|
| 143 |  | 
|---|
| 144 | #[ cfg(feature = "complex")] | 
|---|
| 145 | pub use crate::raw::{ | 
|---|
| 146 | ffi_type_complex_double as complex_double, ffi_type_complex_float as complex_float, | 
|---|
| 147 | }; | 
|---|
| 148 |  | 
|---|
| 149 | #[ cfg(feature = "complex")] | 
|---|
| 150 | #[ cfg(not(all(target_arch = "arm")))] | 
|---|
| 151 | pub use crate::raw::ffi_type_complex_longdouble as complex_longdouble; | 
|---|
| 152 | } | 
|---|
| 153 |  | 
|---|
| 154 | /// Type tags used in constructing and inspecting [`ffi_type`]s. | 
|---|
| 155 | /// | 
|---|
| 156 | /// For atomic types this tag doesn’t matter because libffi predeclares | 
|---|
| 157 | /// [an instance of each one](mod@types). However, for composite | 
|---|
| 158 | /// types (structs and complex numbers), we need to create a new | 
|---|
| 159 | /// instance of the [`ffi_type`] struct. In particular, the `type_` field | 
|---|
| 160 | /// contains a value that indicates what kind of type is represented, | 
|---|
| 161 | /// and we use these values to indicate that that we are describing a | 
|---|
| 162 | /// struct or complex type. | 
|---|
| 163 | /// | 
|---|
| 164 | /// # Examples | 
|---|
| 165 | /// | 
|---|
| 166 | /// Suppose we have the following C struct: | 
|---|
| 167 | /// | 
|---|
| 168 | /// ```c | 
|---|
| 169 | /// struct my_struct { | 
|---|
| 170 | ///     uint16_t f1; | 
|---|
| 171 | ///     uint64_t f2; | 
|---|
| 172 | /// }; | 
|---|
| 173 | /// ``` | 
|---|
| 174 | /// | 
|---|
| 175 | /// To pass it by value to a C function we can construct an | 
|---|
| 176 | /// `ffi_type` as follows using `type_tag::STRUCT`: | 
|---|
| 177 | /// | 
|---|
| 178 | /// ``` | 
|---|
| 179 | /// use std::ptr; | 
|---|
| 180 | /// use libffi::low::{ffi_type, types, type_tag}; | 
|---|
| 181 | /// | 
|---|
| 182 | /// let mut elements = unsafe { | 
|---|
| 183 | ///     [ &mut types::uint16, | 
|---|
| 184 | ///       &mut types::uint64, | 
|---|
| 185 | ///       ptr::null_mut::<ffi_type>() ] | 
|---|
| 186 | /// }; | 
|---|
| 187 | /// | 
|---|
| 188 | /// let mut my_struct: ffi_type = Default::default(); | 
|---|
| 189 | /// my_struct.type_ = type_tag::STRUCT; | 
|---|
| 190 | /// my_struct.elements = elements.as_mut_ptr(); | 
|---|
| 191 | /// ``` | 
|---|
| 192 | pub mod type_tag { | 
|---|
| 193 | use crate::raw; | 
|---|
| 194 | use std::os::raw::c_ushort; | 
|---|
| 195 |  | 
|---|
| 196 | /// Indicates a structure type. | 
|---|
| 197 | pub const STRUCT: c_ushort = raw::ffi_type_enum_STRUCT as c_ushort; | 
|---|
| 198 |  | 
|---|
| 199 | /// Indicates a complex number type. | 
|---|
| 200 | /// | 
|---|
| 201 | /// This item is enabled by `#[cfg(feature = "complex")]`. | 
|---|
| 202 | #[ cfg(feature = "complex")] | 
|---|
| 203 | pub const COMPLEX: c_ushort = raw::ffi_type_enum_COMPLEX as c_ushort; | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | /// Initalizes a CIF (Call Interface) with the given ABI | 
|---|
| 207 | /// and types. | 
|---|
| 208 | /// | 
|---|
| 209 | /// We need to initialize a CIF before we can use it to call a function | 
|---|
| 210 | /// or create a closure. This function lets us specify the calling | 
|---|
| 211 | /// convention to use and the argument and result types. For varargs | 
|---|
| 212 | /// CIF initialization, see [`prep_cif_var`]. | 
|---|
| 213 | /// | 
|---|
| 214 | /// | 
|---|
| 215 | /// # Safety | 
|---|
| 216 | /// | 
|---|
| 217 | /// The CIF `cif` retains references to `rtype` and `atypes`, so if | 
|---|
| 218 | /// they are no longer live when the CIF is used then the behavior is | 
|---|
| 219 | /// undefined. | 
|---|
| 220 | /// | 
|---|
| 221 | /// # Arguments | 
|---|
| 222 | /// | 
|---|
| 223 | /// - `cif` — the CIF to initialize | 
|---|
| 224 | /// - `abi` — the calling convention to use | 
|---|
| 225 | /// - `nargs` — the number of arguments | 
|---|
| 226 | /// - `rtype` — the result type | 
|---|
| 227 | /// - `atypes` — the argument types (length must be at least `nargs`) | 
|---|
| 228 | /// | 
|---|
| 229 | /// # Result | 
|---|
| 230 | /// | 
|---|
| 231 | /// `Ok(())` for success or `Err(e)` for failure. | 
|---|
| 232 | /// | 
|---|
| 233 | /// # Examples | 
|---|
| 234 | /// | 
|---|
| 235 | /// ``` | 
|---|
| 236 | /// use libffi::low::*; | 
|---|
| 237 | /// | 
|---|
| 238 | /// let mut args: [*mut ffi_type; 2] = unsafe { | 
|---|
| 239 | ///     [ &mut types::sint32, | 
|---|
| 240 | ///       &mut types::uint64 ] | 
|---|
| 241 | /// }; | 
|---|
| 242 | /// let mut cif: ffi_cif = Default::default(); | 
|---|
| 243 | /// | 
|---|
| 244 | /// unsafe { | 
|---|
| 245 | ///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 2, | 
|---|
| 246 | ///              &mut types::pointer, args.as_mut_ptr()) | 
|---|
| 247 | /// }.unwrap(); | 
|---|
| 248 | /// ``` | 
|---|
| 249 | pub unsafe fn prep_cif( | 
|---|
| 250 | cif: *mut ffi_cif, | 
|---|
| 251 | abi: ffi_abi, | 
|---|
| 252 | nargs: usize, | 
|---|
| 253 | rtype: *mut ffi_type, | 
|---|
| 254 | atypes: *mut *mut ffi_type, | 
|---|
| 255 | ) -> Result<()> { | 
|---|
| 256 | let status: u32 = raw::ffi_prep_cif(cif, abi, nargs as c_uint, rtype, atypes); | 
|---|
| 257 | status_to_result(status, ()) | 
|---|
| 258 | } | 
|---|
| 259 |  | 
|---|
| 260 | /// Initalizes a CIF (Call Interface) for a varargs function. | 
|---|
| 261 | /// | 
|---|
| 262 | /// We need to initialize a CIF before we can use it to call a function | 
|---|
| 263 | /// or create a closure. This function lets us specify the calling | 
|---|
| 264 | /// convention to use and the argument and result types. For non-varargs | 
|---|
| 265 | /// CIF initialization, see [`prep_cif`]. | 
|---|
| 266 | /// | 
|---|
| 267 | /// # Safety | 
|---|
| 268 | /// | 
|---|
| 269 | /// The CIF `cif` retains references to `rtype` and `atypes`, so if | 
|---|
| 270 | /// they are no longer live when the CIF is used then the behavior is | 
|---|
| 271 | /// undefined. | 
|---|
| 272 | /// | 
|---|
| 273 | /// # Arguments | 
|---|
| 274 | /// | 
|---|
| 275 | /// - `cif` — the CIF to initialize | 
|---|
| 276 | /// - `abi` — the calling convention to use | 
|---|
| 277 | /// - `nfixedargs` — the number of fixed arguments | 
|---|
| 278 | /// - `ntotalargs` — the total number of arguments, including fixed and | 
|---|
| 279 | ///    var args | 
|---|
| 280 | /// - `rtype` — the result type | 
|---|
| 281 | /// - `atypes` — the argument types (length must be at least `nargs`) | 
|---|
| 282 | /// | 
|---|
| 283 | /// # Result | 
|---|
| 284 | /// | 
|---|
| 285 | /// `Ok(())` for success or `Err(e)` for failure. | 
|---|
| 286 | /// | 
|---|
| 287 | pub unsafe fn prep_cif_var( | 
|---|
| 288 | cif: *mut ffi_cif, | 
|---|
| 289 | abi: ffi_abi, | 
|---|
| 290 | nfixedargs: usize, | 
|---|
| 291 | ntotalargs: usize, | 
|---|
| 292 | rtype: *mut ffi_type, | 
|---|
| 293 | atypes: *mut *mut ffi_type, | 
|---|
| 294 | ) -> Result<()> { | 
|---|
| 295 | let status: u32 = raw::ffi_prep_cif_var( | 
|---|
| 296 | cif, | 
|---|
| 297 | abi, | 
|---|
| 298 | nfixedargs as c_uint, | 
|---|
| 299 | ntotalargs as c_uint, | 
|---|
| 300 | rtype, | 
|---|
| 301 | atypes, | 
|---|
| 302 | ); | 
|---|
| 303 | status_to_result(status, ()) | 
|---|
| 304 | } | 
|---|
| 305 |  | 
|---|
| 306 | /// Calls a C function as specified by a CIF. | 
|---|
| 307 | /// | 
|---|
| 308 | /// # Arguments | 
|---|
| 309 | /// | 
|---|
| 310 | /// * `cif` — describes the argument and result types and the calling | 
|---|
| 311 | ///           convention | 
|---|
| 312 | /// * `fun` — the function to call | 
|---|
| 313 | /// * `args` — the arguments to pass to `fun` | 
|---|
| 314 | /// | 
|---|
| 315 | /// # Result | 
|---|
| 316 | /// | 
|---|
| 317 | /// The result of calling `fun` with `args`. | 
|---|
| 318 | /// | 
|---|
| 319 | /// # Examples | 
|---|
| 320 | /// | 
|---|
| 321 | /// ``` | 
|---|
| 322 | /// use std::os::raw::c_void; | 
|---|
| 323 | /// use libffi::low::*; | 
|---|
| 324 | /// | 
|---|
| 325 | /// extern "C"fn c_function(a: u64, b: u64) -> u64 { a + b } | 
|---|
| 326 | /// | 
|---|
| 327 | /// let result = unsafe { | 
|---|
| 328 | ///     let mut args: Vec<*mut ffi_type> = vec![ &mut types::uint64, | 
|---|
| 329 | ///                                              &mut types::uint64 ]; | 
|---|
| 330 | ///     let mut cif: ffi_cif = Default::default(); | 
|---|
| 331 | /// | 
|---|
| 332 | ///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 2, | 
|---|
| 333 | ///              &mut types::uint64, args.as_mut_ptr()).unwrap(); | 
|---|
| 334 | /// | 
|---|
| 335 | ///     call::<u64>(&mut cif, CodePtr(c_function as *mut _), | 
|---|
| 336 | ///          vec![ &mut 4u64 as *mut _ as *mut c_void, | 
|---|
| 337 | ///                &mut 5u64 as *mut _ as *mut c_void ].as_mut_ptr()) | 
|---|
| 338 | /// }; | 
|---|
| 339 | /// | 
|---|
| 340 | /// assert_eq!(9, result); | 
|---|
| 341 | /// ``` | 
|---|
| 342 | pub unsafe fn call<R>(cif: *mut ffi_cif, fun: CodePtr, args: *mut *mut c_void) -> R { | 
|---|
| 343 | let mut result: MaybeUninit = mem::MaybeUninit::<R>::uninit(); | 
|---|
| 344 | raw::ffi_call( | 
|---|
| 345 | cif, | 
|---|
| 346 | fn_:Some(*fun.as_safe_fun()), | 
|---|
| 347 | rvalue:result.as_mut_ptr() as *mut c_void, | 
|---|
| 348 | avalue:args, | 
|---|
| 349 | ); | 
|---|
| 350 | result.assume_init() | 
|---|
| 351 | } | 
|---|
| 352 |  | 
|---|
| 353 | /// Allocates a closure. | 
|---|
| 354 | /// | 
|---|
| 355 | /// Returns a pair of the writable closure object and the function | 
|---|
| 356 | /// pointer for calling it. The former acts as a handle to the closure, | 
|---|
| 357 | /// and is used to configure and free it. The latter is the code pointer | 
|---|
| 358 | /// used to invoke the closure. Before it can be invoked, it must be | 
|---|
| 359 | /// initialized with [`prep_closure`] and [`prep_closure_mut`]. The | 
|---|
| 360 | /// closure must be deallocated using [`closure_free`], after which | 
|---|
| 361 | /// point the code pointer should not be used. | 
|---|
| 362 | /// | 
|---|
| 363 | /// # Examples | 
|---|
| 364 | /// | 
|---|
| 365 | /// ``` | 
|---|
| 366 | /// use libffi::low::*; | 
|---|
| 367 | /// | 
|---|
| 368 | /// let (closure_handle, code_ptr) = closure_alloc(); | 
|---|
| 369 | /// ``` | 
|---|
| 370 | pub fn closure_alloc() -> (*mut ffi_closure, CodePtr) { | 
|---|
| 371 | unsafe { | 
|---|
| 372 | let mut code_pointer: MaybeUninit<*mut c_void> = mem::MaybeUninit::<*mut c_void>::uninit(); | 
|---|
| 373 | let closure: *mut c_void = | 
|---|
| 374 | raw::ffi_closure_alloc(size:mem::size_of::<ffi_closure>(), code_pointer.as_mut_ptr()); | 
|---|
| 375 | ( | 
|---|
| 376 | closure as *mut ffi_closure, | 
|---|
| 377 | CodePtr::from_ptr(fun:code_pointer.assume_init()), | 
|---|
| 378 | ) | 
|---|
| 379 | } | 
|---|
| 380 | } | 
|---|
| 381 |  | 
|---|
| 382 | /// Frees a closure. | 
|---|
| 383 | /// | 
|---|
| 384 | /// Closures allocated with [`closure_alloc`] must be deallocated with | 
|---|
| 385 | /// [`closure_free`]. | 
|---|
| 386 | /// | 
|---|
| 387 | /// # Examples | 
|---|
| 388 | /// | 
|---|
| 389 | /// ``` | 
|---|
| 390 | /// use libffi::low::*; | 
|---|
| 391 | /// | 
|---|
| 392 | /// let (closure_handle, code_ptr) = closure_alloc(); | 
|---|
| 393 | /// | 
|---|
| 394 | /// // ... | 
|---|
| 395 | /// | 
|---|
| 396 | /// unsafe { | 
|---|
| 397 | ///     closure_free(closure_handle); | 
|---|
| 398 | /// } | 
|---|
| 399 | /// ``` | 
|---|
| 400 | pub unsafe fn closure_free(closure: *mut ffi_closure) { | 
|---|
| 401 | raw::ffi_closure_free(arg1:closure as *mut c_void); | 
|---|
| 402 | } | 
|---|
| 403 |  | 
|---|
| 404 | /// The type of function called by a closure. | 
|---|
| 405 | /// | 
|---|
| 406 | /// `U` is the type of the user data captured by the closure and passed | 
|---|
| 407 | /// to the callback, and `R` is the type of the result. The parameters | 
|---|
| 408 | /// are not typed, since they are passed as a C array of `void*`. | 
|---|
| 409 | pub type Callback<U, R> = | 
|---|
| 410 | unsafe extern "C"fn(cif: &ffi_cif, result: &mut R, args: *const *const c_void, userdata: &U); | 
|---|
| 411 |  | 
|---|
| 412 | /// The type of function called by a mutable closure. | 
|---|
| 413 | /// | 
|---|
| 414 | /// `U` is the type of the user data captured by the closure and passed | 
|---|
| 415 | /// to the callback, and `R` is the type of the result. The parameters | 
|---|
| 416 | /// are not typed, since they are passed as a C array of `void*`. | 
|---|
| 417 | pub type CallbackMut<U, R> = unsafe extern "C"fn( | 
|---|
| 418 | cif: &ffi_cif, | 
|---|
| 419 | result: &mut R, | 
|---|
| 420 | args: *const *const c_void, | 
|---|
| 421 | userdata: &mut U, | 
|---|
| 422 | ); | 
|---|
| 423 |  | 
|---|
| 424 | /// The callback type expected by [`raw::ffi_prep_closure_loc`]. | 
|---|
| 425 | pub type RawCallback = unsafe extern "C"fn( | 
|---|
| 426 | cif: *mut ffi_cif, | 
|---|
| 427 | result: *mut c_void, | 
|---|
| 428 | args: *mut *mut c_void, | 
|---|
| 429 | userdata: *mut c_void, | 
|---|
| 430 | ); | 
|---|
| 431 |  | 
|---|
| 432 | /// Initializes a closure with a callback function and userdata. | 
|---|
| 433 | /// | 
|---|
| 434 | /// After allocating a closure with [`closure_alloc`], it needs to be | 
|---|
| 435 | /// initialized with a function `callback` to call and a pointer | 
|---|
| 436 | /// `userdata` to pass to it. Invoking the closure’s code pointer will | 
|---|
| 437 | /// then pass the provided arguments and the user data pointer to the | 
|---|
| 438 | /// callback. | 
|---|
| 439 | /// | 
|---|
| 440 | /// For mutable userdata use [`prep_closure_mut`]. | 
|---|
| 441 | /// | 
|---|
| 442 | /// # Safety | 
|---|
| 443 | /// | 
|---|
| 444 | /// The closure retains a reference to CIF `cif`, so that must | 
|---|
| 445 | /// still be live when the closure is used lest undefined behavior | 
|---|
| 446 | /// result. | 
|---|
| 447 | /// | 
|---|
| 448 | /// # Arguments | 
|---|
| 449 | /// | 
|---|
| 450 | /// - `closure` — the closure to initialize | 
|---|
| 451 | /// - `cif` — the calling convention and types for calling the closure | 
|---|
| 452 | /// - `callback` — the function that the closure will invoke | 
|---|
| 453 | /// - `userdata` — the closed-over value, stored in the closure and | 
|---|
| 454 | ///    passed to the callback upon invocation | 
|---|
| 455 | /// - `code` — the closure’s code pointer, *i.e.*, the second component | 
|---|
| 456 | ///   returned by [`closure_alloc`]. | 
|---|
| 457 | /// | 
|---|
| 458 | /// # Result | 
|---|
| 459 | /// | 
|---|
| 460 | /// `Ok(())` for success or `Err(e)` for failure. | 
|---|
| 461 | /// | 
|---|
| 462 | /// # Examples | 
|---|
| 463 | /// | 
|---|
| 464 | /// ``` | 
|---|
| 465 | /// use libffi::low::*; | 
|---|
| 466 | /// | 
|---|
| 467 | /// use std::mem; | 
|---|
| 468 | /// use std::os::raw::c_void; | 
|---|
| 469 | /// | 
|---|
| 470 | /// unsafe extern "C"fn callback(_cif: &ffi_cif, | 
|---|
| 471 | ///                               result: &mut u64, | 
|---|
| 472 | ///                               args: *const *const c_void, | 
|---|
| 473 | ///                               userdata: &u64) | 
|---|
| 474 | /// { | 
|---|
| 475 | ///     let args: *const &u64 = mem::transmute(args); | 
|---|
| 476 | ///     *result = **args + *userdata; | 
|---|
| 477 | /// } | 
|---|
| 478 | /// | 
|---|
| 479 | /// fn twice(f: extern "C"fn(u64) -> u64, x: u64) -> u64 { | 
|---|
| 480 | ///     f(f(x)) | 
|---|
| 481 | /// } | 
|---|
| 482 | /// | 
|---|
| 483 | /// unsafe { | 
|---|
| 484 | ///     let mut cif: ffi_cif = Default::default(); | 
|---|
| 485 | ///     let mut args = [&mut types::uint64 as *mut _]; | 
|---|
| 486 | ///     let mut userdata: u64 = 5; | 
|---|
| 487 | /// | 
|---|
| 488 | ///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 1, &mut types::uint64, | 
|---|
| 489 | ///              args.as_mut_ptr()).unwrap(); | 
|---|
| 490 | /// | 
|---|
| 491 | ///     let (closure, code) = closure_alloc(); | 
|---|
| 492 | ///     let add5: extern "C"fn(u64) -> u64 = mem::transmute(code); | 
|---|
| 493 | /// | 
|---|
| 494 | ///     prep_closure(closure, | 
|---|
| 495 | ///                  &mut cif, | 
|---|
| 496 | ///                  callback, | 
|---|
| 497 | ///                  &mut userdata, | 
|---|
| 498 | ///                  CodePtr(add5 as *mut _)).unwrap(); | 
|---|
| 499 | /// | 
|---|
| 500 | ///     assert_eq!(11, add5(6)); | 
|---|
| 501 | ///     assert_eq!(12, add5(7)); | 
|---|
| 502 | /// | 
|---|
| 503 | ///     assert_eq!(22, twice(add5, 12)); | 
|---|
| 504 | /// } | 
|---|
| 505 | /// ``` | 
|---|
| 506 | pub unsafe fn prep_closure<U, R>( | 
|---|
| 507 | closure: *mut ffi_closure, | 
|---|
| 508 | cif: *mut ffi_cif, | 
|---|
| 509 | callback: Callback<U, R>, | 
|---|
| 510 | userdata: *const U, | 
|---|
| 511 | code: CodePtr, | 
|---|
| 512 | ) -> Result<()> { | 
|---|
| 513 | let status: u32 = raw::ffi_prep_closure_loc( | 
|---|
| 514 | arg1:closure, | 
|---|
| 515 | arg2:cif, | 
|---|
| 516 | fun:Some(mem::transmute::<Callback<U, R>, RawCallback>(callback)), | 
|---|
| 517 | user_data:userdata as *mut c_void, | 
|---|
| 518 | codeloc:code.as_mut_ptr(), | 
|---|
| 519 | ); | 
|---|
| 520 | status_to_result(status, ()) | 
|---|
| 521 | } | 
|---|
| 522 |  | 
|---|
| 523 | /// Initializes a mutable closure with a callback function and (mutable) | 
|---|
| 524 | /// userdata. | 
|---|
| 525 | /// | 
|---|
| 526 | /// After allocating a closure with [`closure_alloc`], it needs to be | 
|---|
| 527 | /// initialized with a function `callback` to call and a pointer | 
|---|
| 528 | /// `userdata` to pass to it. Invoking the closure’s code pointer will | 
|---|
| 529 | /// then pass the provided arguments and the user data pointer to the | 
|---|
| 530 | /// callback. | 
|---|
| 531 | /// | 
|---|
| 532 | /// For immutable userdata use [`prep_closure`]. | 
|---|
| 533 | /// | 
|---|
| 534 | /// # Safety | 
|---|
| 535 | /// | 
|---|
| 536 | /// The closure retains a reference to CIF `cif`, so that must | 
|---|
| 537 | /// still be live when the closure is used lest undefined behavior | 
|---|
| 538 | /// result. | 
|---|
| 539 | /// | 
|---|
| 540 | /// # Arguments | 
|---|
| 541 | /// | 
|---|
| 542 | /// - `closure` — the closure to initialize | 
|---|
| 543 | /// - `cif` — the calling convention and types for calling the closure | 
|---|
| 544 | /// - `callback` — the function that the closure will invoke | 
|---|
| 545 | /// - `userdata` — the closed-over value, stored in the closure and | 
|---|
| 546 | ///    passed to the callback upon invocation | 
|---|
| 547 | /// - `code` — the closure’s code pointer, *i.e.*, the second component | 
|---|
| 548 | ///   returned by [`closure_alloc`]. | 
|---|
| 549 | /// | 
|---|
| 550 | /// # Result | 
|---|
| 551 | /// | 
|---|
| 552 | /// `Ok(())` for success or `Err(e)` for failure. | 
|---|
| 553 | /// | 
|---|
| 554 | /// # Examples | 
|---|
| 555 | /// | 
|---|
| 556 | /// ``` | 
|---|
| 557 | /// use libffi::low::*; | 
|---|
| 558 | /// | 
|---|
| 559 | /// use std::mem; | 
|---|
| 560 | /// use std::os::raw::c_void; | 
|---|
| 561 | /// | 
|---|
| 562 | /// unsafe extern "C"fn callback(_cif: &ffi_cif, | 
|---|
| 563 | ///                               result: &mut u64, | 
|---|
| 564 | ///                               args: *const *const c_void, | 
|---|
| 565 | ///                               userdata: &mut u64) | 
|---|
| 566 | /// { | 
|---|
| 567 | ///     let args: *const &u64 = mem::transmute(args); | 
|---|
| 568 | ///     *result = *userdata; | 
|---|
| 569 | ///     *userdata += **args; | 
|---|
| 570 | /// } | 
|---|
| 571 | /// | 
|---|
| 572 | /// fn twice(f: extern "C"fn(u64) -> u64, x: u64) -> u64 { | 
|---|
| 573 | ///     f(f(x)) | 
|---|
| 574 | /// } | 
|---|
| 575 | /// | 
|---|
| 576 | /// unsafe { | 
|---|
| 577 | ///     let mut cif: ffi_cif = Default::default(); | 
|---|
| 578 | ///     let mut args = [&mut types::uint64 as *mut _]; | 
|---|
| 579 | ///     let mut userdata: u64 = 5; | 
|---|
| 580 | /// | 
|---|
| 581 | ///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 1, &mut types::uint64, | 
|---|
| 582 | ///              args.as_mut_ptr()).unwrap(); | 
|---|
| 583 | /// | 
|---|
| 584 | ///     let (closure, code) = closure_alloc(); | 
|---|
| 585 | ///     let add5: extern "C"fn(u64) -> u64 = mem::transmute(code); | 
|---|
| 586 | /// | 
|---|
| 587 | ///     prep_closure_mut(closure, | 
|---|
| 588 | ///                      &mut cif, | 
|---|
| 589 | ///                      callback, | 
|---|
| 590 | ///                      &mut userdata, | 
|---|
| 591 | ///                      CodePtr(add5 as *mut _)).unwrap(); | 
|---|
| 592 | /// | 
|---|
| 593 | ///     assert_eq!(5, add5(6)); | 
|---|
| 594 | ///     assert_eq!(11, add5(7)); | 
|---|
| 595 | /// | 
|---|
| 596 | ///     assert_eq!(19, twice(add5, 1)); | 
|---|
| 597 | /// } | 
|---|
| 598 | /// ``` | 
|---|
| 599 | pub unsafe fn prep_closure_mut<U, R>( | 
|---|
| 600 | closure: *mut ffi_closure, | 
|---|
| 601 | cif: *mut ffi_cif, | 
|---|
| 602 | callback: CallbackMut<U, R>, | 
|---|
| 603 | userdata: *mut U, | 
|---|
| 604 | code: CodePtr, | 
|---|
| 605 | ) -> Result<()> { | 
|---|
| 606 | let status: u32 = raw::ffi_prep_closure_loc( | 
|---|
| 607 | arg1:closure, | 
|---|
| 608 | arg2:cif, | 
|---|
| 609 | fun:Some(mem::transmute::<CallbackMut<U, R>, RawCallback>(callback)), | 
|---|
| 610 | user_data:userdata as *mut c_void, | 
|---|
| 611 | codeloc:code.as_mut_ptr(), | 
|---|
| 612 | ); | 
|---|
| 613 | status_to_result(status, ()) | 
|---|
| 614 | } | 
|---|
| 615 |  | 
|---|