1 | //! High layer providing automatic marshalling of Rust closures |
2 | //! as C function pointers. |
3 | //! |
4 | //! The main facility here is given by the structs |
5 | //! <code>Closure<em>N</em></code>, |
6 | //! <code>Closure<span></span>Mut<em>N</em></code>, |
7 | //! and <code>Closure<span></span>Once<em>N</em></code>, |
8 | //! for natural numbers *`N`* |
9 | //! from `0` to `12` (as of |
10 | //! now). These represent C closures of *`N`* arguments, which can be |
11 | //! used to turn Rust lambdas (or in generally, anything that implements |
12 | //! `Fn` or `FnMut`) into ordinary C function pointers. For example, a |
13 | //! Rust value of type `Fn(u32, u32) -> u64` can be turned into a |
14 | //! closure of type [`Closure2<u32, u32, u64>`] using |
15 | //! [`Closure2::new`]. Then a C |
16 | //! function pointer of type `extern "C" fn(u32, u32) -> u64` can be |
17 | //! borrowed from the closure and passed to C. |
18 | //! |
19 | //! The above usage case eliminates much of the boilerplate involved in |
20 | //! creating a closure as compared to the `middle` and `low` layers, but |
21 | //! at the price of flexibility. Some flexibility can be recovered by |
22 | //! manually constructing and configuring a CIF (*e.g.,* a |
23 | //! [`Cif2`]) and then creating the closure with |
24 | //! [`Closure2::new_with_cif`]. |
25 | //! |
26 | //! See the [`mod@call`] submodule for a simple interface |
27 | //! to dynamic calls to C functions. |
28 | //! |
29 | //! # Examples |
30 | //! |
31 | //! Here we use [`ClosureMut1`], which is the type |
32 | //! for creating mutable closures of one argument. We use it to turn a |
33 | //! Rust lambda into a C function pointer. |
34 | //! |
35 | //! ``` |
36 | //! use libffi::high::ClosureMut1; |
37 | //! |
38 | //! let mut x = 0u64; |
39 | //! let mut f = |y: u32| { x += y as u64; x }; |
40 | //! |
41 | //! let closure = ClosureMut1::new(&mut f); |
42 | //! let counter = closure.code_ptr(); |
43 | //! |
44 | //! assert_eq!(5, counter.call(5)); |
45 | //! assert_eq!(6, counter.call(1)); |
46 | //! assert_eq!(8, counter.call(2)); |
47 | //! ``` |
48 | //! |
49 | //! Note that in the above example, `counter` is an ordinary C function |
50 | //! pointer of type `extern "C" fn(u64) -> u64`. |
51 | //! |
52 | //! Here’s an example using `ClosureOnce3` to create a closure that owns |
53 | //! a vector: |
54 | //! |
55 | //! ``` |
56 | //! use libffi::high::ClosureOnce3; |
57 | //! |
58 | //! let v = vec![1, 2, 3, 4, 5]; |
59 | //! let mut f = move |x: usize, y: usize, z: usize| { |
60 | //! v[x] + v[y] + v[z] |
61 | //! }; |
62 | //! |
63 | //! let closure = ClosureOnce3::new(f); |
64 | //! let call = closure.code_ptr(); |
65 | //! |
66 | //! assert_eq!(12, call.call(2, 3, 4)); |
67 | //! ``` |
68 | //! |
69 | //! Invoking the closure a second time will panic. |
70 | |
71 | pub use crate::middle::{ffi_abi_FFI_DEFAULT_ABI, FfiAbi}; |
72 | |
73 | pub mod types; |
74 | pub use types::{CType, Type}; |
75 | |
76 | pub mod call; |
77 | pub use call::*; |
78 | |
79 | macro_rules! abort_on_panic { |
80 | ($msg:literal, $body:expr) => {{ |
81 | // Aborts when dropped (which will only happen due to an unwinding panic). |
82 | struct Bomb; |
83 | impl Drop for Bomb { |
84 | fn drop(&mut self) { |
85 | // We do our best to ignore errors that occur during printing. |
86 | // If this panics anyway, that'll still just be a double-panic which leads to abort. |
87 | let _ = writeln!(std::io::stderr(), $msg); |
88 | std::process::abort(); |
89 | } |
90 | } |
91 | |
92 | let b = Bomb; |
93 | // If this panics, `b` will be dropped, triggering the bomb. |
94 | $body; |
95 | // Defuse the bomb. |
96 | std::mem::forget(b); |
97 | }}; |
98 | } |
99 | |
100 | macro_rules! define_closure_mod { |
101 | ( |
102 | $module:ident $cif:ident $fnptr:ident |
103 | $callback:ident $callback_mut:ident $callback_once:ident |
104 | $closure:ident $closure_mut:ident $closure_once:ident; |
105 | $( $T:ident )* |
106 | ) |
107 | => |
108 | { |
109 | /// CIF and closure types organized by function arity. |
110 | #[allow(clippy::too_many_arguments)] |
111 | pub mod $module { |
112 | use std::any::Any; |
113 | use std::marker::PhantomData; |
114 | use std::{mem, process, ptr}; |
115 | use std::io::{self, Write}; |
116 | |
117 | use super::*; |
118 | use crate::{low, middle}; |
119 | |
120 | /// A typed CIF, which statically tracks argument and result types. |
121 | pub struct $cif<$( $T, )* R> { |
122 | untyped: middle::Cif, |
123 | _marker: PhantomData<fn($( $T, )*) -> R>, |
124 | } |
125 | |
126 | impl<$( $T, )* R> $cif<$( $T, )* R> { |
127 | /// Creates a new statically-typed CIF with the given argument |
128 | /// and result types. |
129 | #[allow(non_snake_case)] |
130 | pub fn new($( $T: Type<$T>, )* result: Type<R>) -> Self { |
131 | let cif = middle::Cif::new( |
132 | vec![$( $T.into_middle() ),*].into_iter(), |
133 | result.into_middle()); |
134 | $cif { untyped: cif, _marker: PhantomData } |
135 | } |
136 | |
137 | /// Sets the CIF to use the given calling convention. |
138 | pub fn set_abi(&mut self, abi: FfiAbi) { |
139 | self.untyped.set_abi(abi); |
140 | } |
141 | } |
142 | |
143 | impl<$( $T: CType, )* R: CType> $cif<$( $T, )* R> { |
144 | /// Creates a new statically-typed CIF by reifying the |
145 | /// argument types as `Type<T>`s. |
146 | pub fn reify() -> Self { |
147 | Self::new($( $T::reify(), )* R::reify()) |
148 | } |
149 | } |
150 | |
151 | /// A lifetime carrying wrapper type for [`fn`] pointers. |
152 | #[derive(Clone, Copy)] |
153 | #[repr(transparent)] |
154 | pub struct $fnptr<'a, $( $T, )* R> { |
155 | func: extern "C" fn($( $T, )*) -> R, |
156 | _lifetime: PhantomData<&'a extern "C" fn($( $T, )*) -> R>, |
157 | } |
158 | impl<'a, $( $T, )* R> $fnptr<'a, $( $T, )* R> { |
159 | /// Call the wrapped [`fn`] pointer. |
160 | // We allow non snake case variable identifiers here because |
161 | // we would otherwise need to take in a whole new list of |
162 | // argument identifiers at every invocation of this macro, |
163 | // and there would be no gain from doing so, since the parameter |
164 | // names here are entirely meaningless. |
165 | #[allow(non_snake_case)] |
166 | pub fn call(&self, $( $T : $T, )*) -> R { |
167 | (self.func)($( $T, )*) |
168 | } |
169 | } |
170 | |
171 | // We use tuples of pointers to describe the arguments, and we |
172 | // extract them by pattern matching. This assumes that a tuple |
173 | // of pointers will be laid out packed and in order. This seems |
174 | // to hold true right now, and I can’t think of a reason why it |
175 | // wouldn’t be that way, but technically it may be undefined |
176 | // behavior. |
177 | |
178 | /// The type of function called from an immutable, typed closure. |
179 | pub type $callback<U, $( $T, )* R> |
180 | = extern "C" fn(cif: &low::ffi_cif, |
181 | result: &mut R, |
182 | args: &($( &$T, )*), |
183 | userdata: &U); |
184 | |
185 | /// An immutable, typed closure with the given argument and result |
186 | /// types. |
187 | pub struct $closure<'a, $( $T, )* R> { |
188 | untyped: middle::Closure<'a>, |
189 | _marker: PhantomData<fn($( $T, )*) -> R>, |
190 | } |
191 | |
192 | impl<'a, $($T: CType,)* R: CType> $closure<'a, $($T,)* R> { |
193 | /// Constructs a typed closure callable from C from a |
194 | /// Rust closure. |
195 | pub fn new<Callback>(callback: &'a Callback) -> Self |
196 | where Callback: Fn($( $T, )*) -> R + 'a |
197 | { |
198 | Self::new_with_cif($cif::reify(), callback) |
199 | } |
200 | } |
201 | |
202 | impl<'a, $( $T, )* R: CType> $closure<'a, $( $T, )* R> { |
203 | /// Gets the C code pointer that is used to invoke the |
204 | /// closure. |
205 | pub fn code_ptr(&self) -> & $fnptr <'a, $( $T, )* R> { |
206 | // Safety: Here we produce an FnPtrN wrapper for |
207 | // the correct `fn` pointer, which is repr(transparent) |
208 | // and therefore reference, layout, and otherwise ABI compatible |
209 | // with that type. |
210 | // Additionally, the FnPtrN wrapper enforces usage of the returned |
211 | // function pointer be only within the lifetime of the closure |
212 | // from which it was made. |
213 | // Other safety invariants have not been checked by |
214 | // the author of this comment, see the `instantiate_code_ptr` |
215 | // method docs for more. |
216 | unsafe { |
217 | self.untyped.instantiate_code_ptr() |
218 | } |
219 | } |
220 | |
221 | /// Constructs a typed closure callable from C from a CIF |
222 | /// describing the calling convention for the resulting |
223 | /// function, a callback for the function to call, and |
224 | /// userdata to pass to the callback. Note that the return |
225 | /// type of the callback must follow the libffi implicit |
226 | /// extension rules. |
227 | pub fn from_parts<U>(cif: $cif<$( $T, )* R>, |
228 | callback: $callback<U, $( $T, )* R::RetType>, |
229 | userdata: &'a U) -> Self |
230 | { |
231 | let callback: middle::Callback<U, R::RetType> |
232 | = unsafe { mem::transmute(callback) }; |
233 | let closure |
234 | = middle::Closure::new(cif.untyped, |
235 | callback, |
236 | userdata); |
237 | $closure { |
238 | untyped: closure, |
239 | _marker: PhantomData, |
240 | } |
241 | } |
242 | } |
243 | |
244 | impl<'a, $( $T: Copy, )* R: CType> $closure<'a, $( $T, )* R> { |
245 | /// Constructs a typed closure callable from C from a CIF |
246 | /// describing the calling convention for the resulting |
247 | /// function and the Rust closure to call. |
248 | pub fn new_with_cif<Callback>(cif: $cif<$( $T, )* R>, |
249 | callback: &'a Callback) -> Self |
250 | where Callback: Fn($( $T, )*) -> R + 'a |
251 | { |
252 | Self::from_parts(cif, |
253 | Self::static_callback, |
254 | callback) |
255 | } |
256 | |
257 | #[allow(non_snake_case)] |
258 | extern "C" fn static_callback<Callback> |
259 | (_cif: &low::ffi_cif, |
260 | result: &mut R::RetType, |
261 | &($( &$T, )*): |
262 | &($( &$T, )*), |
263 | userdata: &Callback) |
264 | where Callback: Fn($( $T, )*) -> R + 'a |
265 | { |
266 | abort_on_panic!("Cannot panic inside FFI callback" , { |
267 | unsafe { |
268 | ptr::write(result, userdata($( $T, )*).into()); |
269 | } |
270 | }); |
271 | } |
272 | } |
273 | |
274 | /// The type of function called from a mutable, typed closure. |
275 | pub type $callback_mut<U, $( $T, )* R> |
276 | = extern "C" fn(cif: &low::ffi_cif, |
277 | result: &mut R, |
278 | args: &($( &$T, )*), |
279 | userdata: &mut U); |
280 | |
281 | /// A mutable, typed closure with the given argument and |
282 | /// result types. |
283 | pub struct $closure_mut<'a, $( $T, )* R> { |
284 | untyped: middle::Closure<'a>, |
285 | _marker: PhantomData<fn($( $T, )*) -> R>, |
286 | } |
287 | |
288 | impl<'a, $($T: CType,)* R: CType> |
289 | $closure_mut<'a, $($T,)* R> |
290 | { |
291 | /// Constructs a typed closure callable from C from a |
292 | /// Rust closure. |
293 | pub fn new<Callback>(callback: &'a mut Callback) -> Self |
294 | where Callback: FnMut($( $T, )*) -> R + 'a |
295 | { |
296 | Self::new_with_cif($cif::reify(), callback) |
297 | } |
298 | } |
299 | |
300 | impl<'a, $( $T, )* R: CType> $closure_mut<'a, $( $T, )* R> { |
301 | /// Gets the C code pointer that is used to invoke the |
302 | /// closure. |
303 | pub fn code_ptr(&self) -> & $fnptr <'a, $( $T, )* R> { |
304 | unsafe { |
305 | self.untyped.instantiate_code_ptr() |
306 | } |
307 | } |
308 | |
309 | /// Constructs a typed closure callable from C from a CIF |
310 | /// describing the calling convention for the resulting |
311 | /// function, a callback for the function to call, and |
312 | /// userdata to pass to the callback. Note that the return |
313 | /// type of the callback must follow the libffi implicit |
314 | /// extension rules. |
315 | pub fn from_parts<U>(cif: $cif<$( $T, )* R>, |
316 | callback: $callback_mut<U, $( $T, )* R::RetType>, |
317 | userdata: &'a mut U) -> Self |
318 | { |
319 | let callback: middle::CallbackMut<U, R::RetType> |
320 | = unsafe { mem::transmute(callback) }; |
321 | let closure |
322 | = middle::Closure::new_mut(cif.untyped, |
323 | callback, |
324 | userdata); |
325 | $closure_mut { |
326 | untyped: closure, |
327 | _marker: PhantomData, |
328 | } |
329 | } |
330 | } |
331 | |
332 | impl<'a, $( $T: Copy, )* R: CType> $closure_mut<'a, $( $T, )* R> { |
333 | /// Constructs a typed closure callable from C from a CIF |
334 | /// describing the calling convention for the resulting |
335 | /// function and the Rust closure to call. |
336 | pub fn new_with_cif<Callback>(cif: $cif<$( $T, )* R>, |
337 | callback: &'a mut Callback) |
338 | -> Self |
339 | where Callback: FnMut($( $T, )*) -> R + 'a |
340 | { |
341 | Self::from_parts(cif, |
342 | Self::static_callback, |
343 | callback) |
344 | } |
345 | |
346 | #[allow(non_snake_case)] |
347 | extern "C" fn static_callback<Callback> |
348 | (_cif: &low::ffi_cif, |
349 | result: &mut R::RetType, |
350 | &($( &$T, )*): |
351 | &($( &$T, )*), |
352 | userdata: &mut Callback) |
353 | where Callback: FnMut($( $T, )*) -> R + 'a |
354 | { |
355 | abort_on_panic!("Cannot panic inside FFI callback" , { |
356 | unsafe { |
357 | ptr::write(result, userdata($( $T, )*).into()); |
358 | } |
359 | }); |
360 | } |
361 | } |
362 | |
363 | /// The type of function called from a one-shot, typed closure. |
364 | pub type $callback_once<U, $( $T, )* R> |
365 | = $callback_mut<Option<U>, $( $T, )* R>; |
366 | |
367 | /// A one-shot, typed closure with the given argument and |
368 | /// result types. |
369 | pub struct $closure_once<$( $T, )* R> { |
370 | untyped: middle::ClosureOnce, |
371 | _marker: PhantomData<fn($( $T, )*) -> R>, |
372 | } |
373 | |
374 | impl<$($T: CType,)* R: CType> $closure_once<$($T,)* R> { |
375 | /// Constructs a typed closure callable from C from a |
376 | /// Rust closure. |
377 | pub fn new<Callback>(callback: Callback) -> Self |
378 | where Callback: FnOnce($( $T, )*) -> R + Any |
379 | { |
380 | Self::new_with_cif($cif::reify(), callback) |
381 | } |
382 | } |
383 | |
384 | impl<$( $T: Copy, )* R: CType> $closure_once<$( $T, )* R> { |
385 | /// Constructs a one-shot closure callable from C from a CIF |
386 | /// describing the calling convention for the resulting |
387 | /// function and the Rust closure to call. |
388 | pub fn new_with_cif<Callback>(cif: $cif<$( $T, )* R>, |
389 | callback: Callback) -> Self |
390 | where Callback: FnOnce($( $T, )*) -> R + Any |
391 | { |
392 | Self::from_parts(cif, |
393 | Self::static_callback, |
394 | callback) |
395 | } |
396 | |
397 | #[allow(non_snake_case)] |
398 | extern "C" fn static_callback<Callback> |
399 | (_cif: &low::ffi_cif, |
400 | result: &mut R::RetType, |
401 | &($( &$T, )*): |
402 | &($( &$T, )*), |
403 | userdata: &mut Option<Callback>) |
404 | where Callback: FnOnce($( $T, )*) -> R |
405 | { |
406 | if let Some(userdata) = userdata.take() { |
407 | abort_on_panic!("Cannot panic inside FFI callback" , { |
408 | unsafe { |
409 | ptr::write(result, userdata($( $T, )*).into()); |
410 | } |
411 | }); |
412 | } else { |
413 | // There is probably a better way to abort here. |
414 | let _ = |
415 | io::stderr().write(b"FnOnce closure already used" ); |
416 | process::exit(2); |
417 | } |
418 | } |
419 | } |
420 | |
421 | impl<$( $T, )* R: CType> $closure_once<$( $T, )* R> { |
422 | /// Gets the C code pointer that is used to invoke the |
423 | /// closure. |
424 | pub fn code_ptr(&self) -> & $fnptr <'_, $( $T, )* R> { |
425 | unsafe { |
426 | self.untyped.instantiate_code_ptr() |
427 | } |
428 | } |
429 | |
430 | /// Constructs a one-shot closure callable from C from a CIF |
431 | /// describing the calling convention for the resulting |
432 | /// function, a callback for the function to call, and |
433 | /// userdata to pass to the callback. Note that the return |
434 | /// type of the callback must follow the libffi implicit |
435 | /// extension rules. |
436 | pub fn from_parts<U: Any>( |
437 | cif: $cif<$( $T, )* R>, |
438 | callback: $callback_once<U, $( $T, )* R::RetType>, |
439 | userdata: U) |
440 | -> Self |
441 | { |
442 | let callback: middle::CallbackOnce<U, R::RetType> |
443 | = unsafe { mem::transmute(callback) }; |
444 | let closure |
445 | = middle::ClosureOnce::new(cif.untyped, |
446 | callback, |
447 | userdata); |
448 | $closure_once { |
449 | untyped: closure, |
450 | _marker: PhantomData, |
451 | } |
452 | } |
453 | } |
454 | } |
455 | |
456 | pub use $module::*; |
457 | } |
458 | } |
459 | |
460 | define_closure_mod!(arity0 Cif0 FnPtr0 |
461 | Callback0 CallbackMut0 CallbackOnce0 |
462 | Closure0 ClosureMut0 ClosureOnce0; |
463 | ); |
464 | define_closure_mod!(arity1 Cif1 FnPtr1 |
465 | Callback1 CallbackMut1 CallbackOnce1 |
466 | Closure1 ClosureMut1 ClosureOnce1; |
467 | A); |
468 | define_closure_mod!(arity2 Cif2 FnPtr2 |
469 | Callback2 CallbackMut2 CallbackOnce2 |
470 | Closure2 ClosureMut2 ClosureOnce2; |
471 | A B); |
472 | define_closure_mod!(arity3 Cif3 FnPtr3 |
473 | Callback3 CallbackMut3 CallbackOnce3 |
474 | Closure3 ClosureMut3 ClosureOnce3; |
475 | A B C); |
476 | define_closure_mod!(arity4 Cif4 FnPtr4 |
477 | Callback4 CallbackMut4 CallbackOnce4 |
478 | Closure4 ClosureMut4 ClosureOnce4; |
479 | A B C D); |
480 | define_closure_mod!(arity5 Cif5 FnPtr5 |
481 | Callback5 CallbackMut5 CallbackOnce5 |
482 | Closure5 ClosureMut5 ClosureOnce5; |
483 | A B C D E); |
484 | define_closure_mod!(arity6 Cif6 FnPtr6 |
485 | Callback6 CallbackMut6 CallbackOnce6 |
486 | Closure6 ClosureMut6 ClosureOnce6; |
487 | A B C D E F); |
488 | define_closure_mod!(arity7 Cif7 FnPtr7 |
489 | Callback7 CallbackMut7 CallbackOnce7 |
490 | Closure7 ClosureMut7 ClosureOnce7; |
491 | A B C D E F G); |
492 | define_closure_mod!(arity8 Cif8 FnPtr8 |
493 | Callback8 CallbackMut8 CallbackOnce8 |
494 | Closure8 ClosureMut8 ClosureOnce8; |
495 | A B C D E F G H); |
496 | define_closure_mod!(arity9 Cif9 FnPtr9 |
497 | Callback9 CallbackMut9 CallbackOnce9 |
498 | Closure9 ClosureMut9 ClosureOnce9; |
499 | A B C D E F G H I); |
500 | define_closure_mod!(arity10 Cif10 FnPtr10 |
501 | Callback10 CallbackMut10 CallbackOnce10 |
502 | Closure10 ClosureMut10 ClosureOnce10; |
503 | A B C D E F G H I J); |
504 | define_closure_mod!(arity11 Cif11 FnPtr11 |
505 | Callback11 CallbackMut11 CallbackOnce11 |
506 | Closure11 ClosureMut11 ClosureOnce11; |
507 | A B C D E F G H I J K); |
508 | define_closure_mod!(arity12 Cif12 FnPtr12 |
509 | Callback12 CallbackMut12 CallbackOnce12 |
510 | Closure12 ClosureMut12 ClosureOnce12; |
511 | A B C D E F G H I J K L); |
512 | |
513 | #[cfg (test)] |
514 | mod test { |
515 | use super::*; |
516 | |
517 | #[test ] |
518 | fn new_with_cif() { |
519 | let x: u64 = 1; |
520 | let f = |y: u64, z: u64| x + y + z; |
521 | |
522 | let type_ = u64::reify(); |
523 | let cif = Cif2::new(type_.clone(), type_.clone(), type_.clone()); |
524 | let closure = Closure2::new_with_cif(cif, &f); |
525 | |
526 | assert_eq!(12, closure.code_ptr().call(5, 6)); |
527 | } |
528 | |
529 | #[test ] |
530 | fn new_with_cif_mut() { |
531 | let mut x: u64 = 0; |
532 | let mut f = |y: u64| { |
533 | x += y; |
534 | x |
535 | }; |
536 | |
537 | let type_ = u64::reify(); |
538 | let cif = Cif1::new(type_.clone(), type_.clone()); |
539 | let closure = ClosureMut1::new_with_cif(cif, &mut f); |
540 | |
541 | let counter = closure.code_ptr(); |
542 | |
543 | assert_eq!(5, counter.call(5)); |
544 | assert_eq!(6, counter.call(1)); |
545 | assert_eq!(8, counter.call(2)); |
546 | } |
547 | |
548 | #[test ] |
549 | fn new() { |
550 | let x: u64 = 1; |
551 | let f = |y: u64, z: u64| x + y + z; |
552 | |
553 | let closure = Closure2::new(&f); |
554 | |
555 | assert_eq!(12, closure.code_ptr().call(5, 6)); |
556 | } |
557 | |
558 | #[test ] |
559 | fn new_mut() { |
560 | let mut x: u64 = 0; |
561 | let mut f = |y: u32| { |
562 | x += u64::from(y); |
563 | x |
564 | }; |
565 | |
566 | let closure = ClosureMut1::new(&mut f); |
567 | let counter = closure.code_ptr(); |
568 | |
569 | assert_eq!(5, counter.call(5)); |
570 | assert_eq!(6, counter.call(1)); |
571 | assert_eq!(8, counter.call(2)); |
572 | } |
573 | } |
574 | |