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