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
71pub use crate::middle::{ffi_abi_FFI_DEFAULT_ABI, FfiAbi};
72
73pub mod types;
74pub use types::{CType, Type};
75
76pub mod call;
77pub use call::*;
78
79macro_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
100macro_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
460define_closure_mod!(arity0 Cif0 FnPtr0
461Callback0 CallbackMut0 CallbackOnce0
462Closure0 ClosureMut0 ClosureOnce0;
463);
464define_closure_mod!(arity1 Cif1 FnPtr1
465 Callback1 CallbackMut1 CallbackOnce1
466 Closure1 ClosureMut1 ClosureOnce1;
467 A);
468define_closure_mod!(arity2 Cif2 FnPtr2
469 Callback2 CallbackMut2 CallbackOnce2
470 Closure2 ClosureMut2 ClosureOnce2;
471 A B);
472define_closure_mod!(arity3 Cif3 FnPtr3
473 Callback3 CallbackMut3 CallbackOnce3
474 Closure3 ClosureMut3 ClosureOnce3;
475 A B C);
476define_closure_mod!(arity4 Cif4 FnPtr4
477 Callback4 CallbackMut4 CallbackOnce4
478 Closure4 ClosureMut4 ClosureOnce4;
479 A B C D);
480define_closure_mod!(arity5 Cif5 FnPtr5
481 Callback5 CallbackMut5 CallbackOnce5
482 Closure5 ClosureMut5 ClosureOnce5;
483 A B C D E);
484define_closure_mod!(arity6 Cif6 FnPtr6
485 Callback6 CallbackMut6 CallbackOnce6
486 Closure6 ClosureMut6 ClosureOnce6;
487 A B C D E F);
488define_closure_mod!(arity7 Cif7 FnPtr7
489 Callback7 CallbackMut7 CallbackOnce7
490 Closure7 ClosureMut7 ClosureOnce7;
491 A B C D E F G);
492define_closure_mod!(arity8 Cif8 FnPtr8
493 Callback8 CallbackMut8 CallbackOnce8
494 Closure8 ClosureMut8 ClosureOnce8;
495 A B C D E F G H);
496define_closure_mod!(arity9 Cif9 FnPtr9
497 Callback9 CallbackMut9 CallbackOnce9
498 Closure9 ClosureMut9 ClosureOnce9;
499 A B C D E F G H I);
500define_closure_mod!(arity10 Cif10 FnPtr10
501 Callback10 CallbackMut10 CallbackOnce10
502 Closure10 ClosureMut10 ClosureOnce10;
503 A B C D E F G H I J);
504define_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);
508define_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)]
514mod 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