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