deno_libffi/high/
mod.rs

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`](struct.Closure2.html#method.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`](struct.Cif2.html)) and then creating the closure with
24//! [`Closure2::new_with_cif`](struct.Closure2.html#method.new_with_cif).
25//!
26//! See the [`call`](call/index.html) submodule for a simple interface
27//! to dynamic calls to C functions.
28//!
29//! # Examples
30//!
31//! Here we use [`ClosureMut1`](struct.ClosureMut1.html), 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 deno_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(5));
45//! assert_eq!(6, counter(1));
46//! assert_eq!(8, counter(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 deno_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(2, 3, 4));
67//! ```
68//!
69//! Invoking the closure a second time will panic.
70
71use abort_on_panic::abort_on_panic;
72
73pub use crate::middle::{ffi_abi_FFI_DEFAULT_ABI, FfiAbi};
74
75pub mod types;
76pub use types::{CType, Type};
77
78pub mod call;
79pub use call::*;
80
81macro_rules! define_closure_mod {
82    (
83        $module:ident $cif:ident
84          $callback:ident $callback_mut:ident $callback_once:ident
85          $closure:ident $closure_mut:ident $closure_once:ident;
86        $( $T:ident )*
87    )
88        =>
89    {
90        /// CIF and closure types organized by function arity.
91        #[allow(clippy::too_many_arguments)]
92        pub mod $module {
93            use std::any::Any;
94            use std::marker::PhantomData;
95            use std::{mem, process, ptr};
96            use std::io::{self, Write};
97
98            use super::*;
99            use crate::{low, middle};
100
101            /// A typed CIF, which statically tracks argument and result types.
102            pub struct $cif<$( $T, )* R> {
103                untyped: middle::Cif,
104                _marker: PhantomData<fn($( $T, )*) -> R>,
105            }
106
107            impl<$( $T, )* R> $cif<$( $T, )* R> {
108                /// Creates a new statically-typed CIF with the given argument
109                /// and result types.
110                #[allow(non_snake_case)]
111                pub fn new($( $T: Type<$T>, )* result: Type<R>) -> Self {
112                    let cif = middle::Cif::new(
113                        vec![$( $T.into_middle() ),*].into_iter(),
114                        result.into_middle());
115                    $cif { untyped: cif, _marker: PhantomData }
116                }
117
118                /// Sets the CIF to use the given calling convention.
119                pub fn set_abi(&mut self, abi: FfiAbi) {
120                    self.untyped.set_abi(abi);
121                }
122            }
123
124            impl<$( $T: CType, )* R: CType> $cif<$( $T, )* R> {
125                /// Creates a new statically-typed CIF by reifying the
126                /// argument types as `Type<T>`s.
127                pub fn reify() -> Self {
128                    Self::new($( $T::reify(), )* R::reify())
129                }
130            }
131
132            // We use tuples of pointers to describe the arguments, and we
133            // extract them by pattern matching. This assumes that a tuple
134            // of pointers will be laid out packed and in order. This seems
135            // to hold true right now, and I can’t think of a reason why it
136            // wouldn’t be that way, but technically it may be undefined
137            // behavior.
138
139            /// The type of function called from an immutable, typed closure.
140            pub type $callback<U, $( $T, )* R>
141                = extern "C" fn(cif:      &low::ffi_cif,
142                                result:   &mut R,
143                                args:     &($( &$T, )*),
144                                userdata: &U);
145
146            /// An immutable, typed closure with the given argument and result
147            /// types.
148            pub struct $closure<'a, $( $T, )* R> {
149                untyped: middle::Closure<'a>,
150                _marker: PhantomData<fn($( $T, )*) -> R>,
151            }
152
153            impl<'a, $($T: CType,)* R: CType> $closure<'a, $($T,)* R> {
154                /// Constructs a typed closure callable from C from a
155                /// Rust closure.
156                pub fn new<Callback>(callback: &'a Callback) -> Self
157                    where Callback: Fn($( $T, )*) -> R + 'a
158                {
159                    Self::new_with_cif($cif::reify(), callback)
160                }
161            }
162
163            impl<'a, $( $T, )* R> $closure<'a, $( $T, )* R> {
164                /// Gets the C code pointer that is used to invoke the
165                /// closure.
166                pub fn code_ptr(&self) -> &extern "C" fn($( $T, )*) -> R {
167                    unsafe {
168                        self.untyped.instantiate_code_ptr()
169                    }
170                }
171
172                /// Constructs a typed closure callable from C from a CIF
173                /// describing the calling convention for the resulting
174                /// function, a callback for the function to call, and
175                /// userdata to pass to the callback.
176                pub fn from_parts<U>(cif: $cif<$( $T, )* R>,
177                                     callback: $callback<U, $( $T, )* R>,
178                                     userdata: &'a U) -> Self
179                {
180                    let callback: middle::Callback<U, R>
181                        = unsafe { mem::transmute(callback) };
182                    let closure
183                        = middle::Closure::new(cif.untyped,
184                                               callback,
185                                               userdata);
186                    $closure {
187                        untyped: closure,
188                        _marker: PhantomData,
189                    }
190                }
191            }
192
193            impl<'a, $( $T: Copy, )* R> $closure<'a, $( $T, )* R> {
194                /// Constructs a typed closure callable from C from a CIF
195                /// describing the calling convention for the resulting
196                /// function and the Rust closure to call.
197                pub fn new_with_cif<Callback>(cif: $cif<$( $T, )* R>,
198                                              callback: &'a Callback) -> Self
199                    where Callback: Fn($( $T, )*) -> R + 'a
200                {
201                    Self::from_parts(cif,
202                                     Self::static_callback,
203                                     callback)
204                }
205
206                #[allow(non_snake_case)]
207                extern "C" fn static_callback<Callback>
208                    (_cif:     &low::ffi_cif,
209                     result:   &mut R,
210                     &($( &$T, )*):
211                               &($( &$T, )*),
212                     userdata: &Callback)
213                  where Callback: Fn($( $T, )*) -> R + 'a
214                {
215                    abort_on_panic!("Cannot panic inside FFI callback", {
216                        unsafe {
217                            ptr::write(result, userdata($( $T, )*));
218                        }
219                    });
220                }
221            }
222
223            /// The type of function called from a mutable, typed closure.
224            pub type $callback_mut<U, $( $T, )* R>
225                = extern "C" fn(cif:      &low::ffi_cif,
226                                result:   &mut R,
227                                args:     &($( &$T, )*),
228                                userdata: &mut U);
229
230            /// A mutable, typed closure with the given argument and
231            /// result types.
232            pub struct $closure_mut<'a, $( $T, )* R> {
233                untyped: middle::Closure<'a>,
234                _marker: PhantomData<fn($( $T, )*) -> R>,
235            }
236
237            impl<'a, $($T: CType,)* R: CType>
238                $closure_mut<'a, $($T,)* R>
239            {
240                /// Constructs a typed closure callable from C from a
241                /// Rust closure.
242                pub fn new<Callback>(callback: &'a mut Callback) -> Self
243                    where Callback: FnMut($( $T, )*) -> R + 'a
244                {
245                    Self::new_with_cif($cif::reify(), callback)
246                }
247            }
248
249            impl<'a, $( $T, )* R> $closure_mut<'a, $( $T, )* R> {
250                /// Gets the C code pointer that is used to invoke the
251                /// closure.
252                pub fn code_ptr(&self) -> &extern "C" fn($( $T, )*) -> R {
253                    unsafe {
254                        self.untyped.instantiate_code_ptr()
255                    }
256                }
257
258                /// Constructs a typed closure callable from C from a CIF
259                /// describing the calling convention for the resulting
260                /// function, a callback for the function to call, and
261                /// userdata to pass to the callback.
262                pub fn from_parts<U>(cif:      $cif<$( $T, )* R>,
263                                     callback: $callback_mut<U, $( $T, )* R>,
264                                     userdata: &'a mut U) -> Self
265                {
266                    let callback: middle::CallbackMut<U, R>
267                        = unsafe { mem::transmute(callback) };
268                    let closure
269                        = middle::Closure::new_mut(cif.untyped,
270                                                   callback,
271                                                   userdata);
272                    $closure_mut {
273                        untyped: closure,
274                        _marker: PhantomData,
275                    }
276                }
277            }
278
279            impl<'a, $( $T: Copy, )* R> $closure_mut<'a, $( $T, )* R> {
280                /// Constructs a typed closure callable from C from a CIF
281                /// describing the calling convention for the resulting
282                /// function and the Rust closure to call.
283                pub fn new_with_cif<Callback>(cif: $cif<$( $T, )* R>,
284                                              callback: &'a mut Callback)
285                                              -> Self
286                    where Callback: FnMut($( $T, )*) -> R + 'a
287                {
288                    Self::from_parts(cif,
289                                     Self::static_callback,
290                                     callback)
291                }
292
293                #[allow(non_snake_case)]
294                extern "C" fn static_callback<Callback>
295                    (_cif:     &low::ffi_cif,
296                     result:   &mut R,
297                     &($( &$T, )*):
298                               &($( &$T, )*),
299                     userdata: &mut Callback)
300                  where Callback: FnMut($( $T, )*) -> R + 'a
301                {
302                    abort_on_panic!("Cannot panic inside FFI callback", {
303                        unsafe {
304                            ptr::write(result, userdata($( $T, )*));
305                        }
306                    });
307                }
308            }
309
310            /// The type of function called from a one-shot, typed closure.
311            pub type $callback_once<U, $( $T, )* R>
312                = $callback_mut<Option<U>, $( $T, )* R>;
313
314            /// A one-shot, typed closure with the given argument and
315            /// result types.
316            pub struct $closure_once<$( $T, )* R> {
317                untyped: middle::ClosureOnce,
318                _marker: PhantomData<fn($( $T, )*) -> R>,
319            }
320
321            impl<$($T: CType,)* R: CType> $closure_once<$($T,)* R> {
322                /// Constructs a typed closure callable from C from a
323                /// Rust closure.
324                pub fn new<Callback>(callback: Callback) -> Self
325                    where Callback: FnOnce($( $T, )*) -> R + Any
326                {
327                    Self::new_with_cif($cif::reify(), callback)
328                }
329            }
330
331            impl<$( $T: Copy, )* R> $closure_once<$( $T, )* R> {
332                /// Constructs a one-shot closure callable from C from a CIF
333                /// describing the calling convention for the resulting
334                /// function and the Rust closure to call.
335                pub fn new_with_cif<Callback>(cif: $cif<$( $T, )* R>,
336                                              callback: Callback) -> Self
337                    where Callback: FnOnce($( $T, )*) -> R + Any
338                {
339                    Self::from_parts(cif,
340                                     Self::static_callback,
341                                     callback)
342                }
343
344                #[allow(non_snake_case)]
345                extern "C" fn static_callback<Callback>
346                    (_cif:     &low::ffi_cif,
347                     result:   &mut R,
348                     &($( &$T, )*):
349                               &($( &$T, )*),
350                     userdata: &mut Option<Callback>)
351                  where Callback: FnOnce($( $T, )*) -> R
352                {
353                    if let Some(userdata) = userdata.take() {
354                        abort_on_panic!("Cannot panic inside FFI callback", {
355                            unsafe {
356                                ptr::write(result, userdata($( $T, )*));
357                            }
358                        });
359                    } else {
360                        // There is probably a better way to abort here.
361                        let _ =
362                            io::stderr().write(b"FnOnce closure already used");
363                        process::exit(2);
364                    }
365                }
366            }
367
368            impl<$( $T, )* R> $closure_once<$( $T, )* R> {
369                /// Gets the C code pointer that is used to invoke the
370                /// closure.
371                pub fn code_ptr(&self) -> &extern "C" fn($( $T, )*) -> R {
372                    unsafe {
373                        self.untyped.instantiate_code_ptr()
374                    }
375                }
376
377                /// Constructs a one-shot closure callable from C from a CIF
378                /// describing the calling convention for the resulting
379                /// function, a callback for the function to call, and
380                /// userdata to pass to the callback.
381                pub fn from_parts<U: Any>(
382                    cif:      $cif<$( $T, )* R>,
383                    callback: $callback_once<U, $( $T, )* R>,
384                    userdata: U)
385                    -> Self
386                {
387                    let callback: middle::CallbackOnce<U, R>
388                        = unsafe { mem::transmute(callback) };
389                    let closure
390                        = middle::ClosureOnce::new(cif.untyped,
391                                                   callback,
392                                                   userdata);
393                    $closure_once {
394                        untyped: closure,
395                        _marker: PhantomData,
396                    }
397                }
398            }
399        }
400
401        pub use $module::*;
402    }
403}
404
405define_closure_mod!(arity0 Cif0
406Callback0 CallbackMut0 CallbackOnce0
407Closure0 ClosureMut0 ClosureOnce0;
408);
409define_closure_mod!(arity1 Cif1
410                    Callback1 CallbackMut1 CallbackOnce1
411                    Closure1 ClosureMut1 ClosureOnce1;
412                    A);
413define_closure_mod!(arity2 Cif2
414                    Callback2 CallbackMut2 CallbackOnce2
415                    Closure2 ClosureMut2 ClosureOnce2;
416                    A B);
417define_closure_mod!(arity3 Cif3
418                    Callback3 CallbackMut3 CallbackOnce3
419                    Closure3 ClosureMut3 ClosureOnce3;
420                    A B C);
421define_closure_mod!(arity4 Cif4
422                    Callback4 CallbackMut4 CallbackOnce4
423                    Closure4 ClosureMut4 ClosureOnce4;
424                    A B C D);
425define_closure_mod!(arity5 Cif5
426                    Callback5 CallbackMut5 CallbackOnce5
427                    Closure5 ClosureMut5 ClosureOnce5;
428                    A B C D E);
429define_closure_mod!(arity6 Cif6
430                    Callback6 CallbackMut6 CallbackOnce6
431                    Closure6 ClosureMut6 ClosureOnce6;
432                    A B C D E F);
433define_closure_mod!(arity7 Cif7
434                    Callback7 CallbackMut7 CallbackOnce7
435                    Closure7 ClosureMut7 ClosureOnce7;
436                    A B C D E F G);
437define_closure_mod!(arity8 Cif8
438                    Callback8 CallbackMut8 CallbackOnce8
439                    Closure8 ClosureMut8 ClosureOnce8;
440                    A B C D E F G H);
441define_closure_mod!(arity9 Cif9
442                    Callback9 CallbackMut9 CallbackOnce9
443                    Closure9 ClosureMut9 ClosureOnce9;
444                    A B C D E F G H I);
445define_closure_mod!(arity10 Cif10
446                    Callback10 CallbackMut10 CallbackOnce10
447                    Closure10 ClosureMut10 ClosureOnce10;
448                    A B C D E F G H I J);
449define_closure_mod!(arity11 Cif11
450                    Callback11 CallbackMut11 CallbackOnce11
451                    Closure11 ClosureMut11 ClosureOnce11;
452                    A B C D E F G H I J K);
453define_closure_mod!(arity12 Cif12
454                    Callback12 CallbackMut12 CallbackOnce12
455                    Closure12 ClosureMut12 ClosureOnce12;
456                    A B C D E F G H I J K L);
457
458#[cfg(test)]
459mod test {
460    use super::*;
461
462    #[test]
463    fn new_with_cif() {
464        let x: u64 = 1;
465        let f = |y: u64, z: u64| x + y + z;
466
467        let type_ = u64::reify();
468        let cif = Cif2::new(type_.clone(), type_.clone(), type_.clone());
469        let closure = Closure2::new_with_cif(cif, &f);
470
471        assert_eq!(12, closure.code_ptr()(5, 6));
472    }
473
474    #[test]
475    fn new_with_cif_mut() {
476        let mut x: u64 = 0;
477        let mut f = |y: u64| {
478            x += y;
479            x
480        };
481
482        let type_ = u64::reify();
483        let cif = Cif1::new(type_.clone(), type_.clone());
484        let closure = ClosureMut1::new_with_cif(cif, &mut f);
485
486        let counter = closure.code_ptr();
487
488        assert_eq!(5, counter(5));
489        assert_eq!(6, counter(1));
490        assert_eq!(8, counter(2));
491    }
492
493    #[test]
494    fn new() {
495        let x: u64 = 1;
496        let f = |y: u64, z: u64| x + y + z;
497
498        let closure = Closure2::new(&f);
499
500        assert_eq!(12, closure.code_ptr()(5, 6));
501    }
502
503    #[test]
504    fn new_mut() {
505        let mut x: u64 = 0;
506        let mut f = |y: u32| {
507            x += u64::from(y);
508            x
509        };
510
511        let closure = ClosureMut1::new(&mut f);
512        let counter = closure.code_ptr();
513
514        assert_eq!(5, counter(5));
515        assert_eq!(6, counter(1));
516        assert_eq!(8, counter(2));
517    }
518}