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}