deno_libffi/
low.rs

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`](../raw/index.html), I’ve
7//! avoided drastic renaming in favor of hewing close to the libffi API.
8//! See [`middle`](../middle/index.html) for an easier-to-use approach.
9
10use std::mem;
11use std::os::raw::{c_uint, c_void};
12
13use crate::raw;
14
15/// The two kinds of errors reported by libffi.
16#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
17pub 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 `Result` type specialized for libffi `Error`s.
25pub type Result<T> = ::std::result::Result<T, Error>;
26
27// Converts the raw status type to a `Result`.
28fn 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)]
48pub struct CodePtr(pub *mut c_void);
49
50// How useful is this type? Does it need all the methods?
51impl 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
123pub use raw::{ffi_abi, ffi_abi_FFI_DEFAULT_ABI, ffi_cif, ffi_closure, ffi_status, ffi_type};
124
125/// Re-exports the `ffi_type` objects used to describe the types of
126/// arguments and results.
127///
128/// These are from [`raw`](../../raw/index.html), but are renamed by
129/// removing the `ffi_type_` prefix. For example, `raw::ffi_type_void`
130/// becomes `low::types::void`.
131pub mod types {
132    pub use crate::raw::{
133        ffi_type_double as double, ffi_type_float as float, ffi_type_pointer as pointer,
134        ffi_type_sint16 as sint16, ffi_type_sint32 as sint32, ffi_type_sint64 as sint64,
135        ffi_type_sint8 as sint8, ffi_type_uint16 as uint16, ffi_type_uint32 as uint32,
136        ffi_type_uint64 as uint64, ffi_type_uint8 as uint8, ffi_type_void as void,
137    };
138
139    #[cfg(not(all(target_arch = "arm")))]
140    pub use crate::raw::ffi_type_longdouble as longdouble;
141
142    #[cfg(feature = "complex")]
143    pub use crate::raw::{
144        ffi_type_complex_double as complex_double, ffi_type_complex_float as complex_float,
145    };
146
147    #[cfg(feature = "complex")]
148    #[cfg(not(all(target_arch = "arm")))]
149    pub use crate::raw::ffi_type_complex_longdouble as complex_longdouble;
150}
151
152/// Type tags used in constructing and inspecting `ffi_type`s.
153///
154/// For atomic types this tag doesn’t matter because libffi predeclares
155/// [an instance of each one](types/index.html). However, for composite
156/// types (structs and complex numbers), we need to create a new
157/// instance of the `ffi_type` struct. In particular, the `type_` field
158/// contains a value that indicates what kind of type is represented,
159/// and we use these values to indicate that that we are describing a
160/// struct or complex type.
161///
162/// # Examples
163///
164/// Suppose we have the following C struct:
165///
166/// ```c
167/// struct my_struct {
168///     uint16_t f1;
169///     uint64_t f2;
170/// };
171/// ```
172///
173/// To pass it by value to a C function we can construct an
174/// `ffi_type` as follows using `type_tag::STRUCT`:
175///
176/// ```
177/// use std::ptr;
178/// use deno_libffi::low::{ffi_type, types, type_tag};
179///
180/// let mut elements = unsafe {
181///     [ &mut types::uint16,
182///       &mut types::uint64,
183///       ptr::null_mut::<ffi_type>() ]
184/// };
185///
186/// let mut my_struct: ffi_type = Default::default();
187/// my_struct.type_ = type_tag::STRUCT;
188/// my_struct.elements = elements.as_mut_ptr();
189/// ```
190pub mod type_tag {
191    use crate::raw;
192    use std::os::raw::c_ushort;
193
194    /// Indicates a structure type.
195    pub const STRUCT: c_ushort = raw::ffi_type_enum_STRUCT as c_ushort;
196
197    /// Indicates a complex number type.
198    ///
199    /// This item is enabled by `#[cfg(feature = "complex")]`.
200    #[cfg(feature = "complex")]
201    pub const COMPLEX: c_ushort = raw::ffi_type_enum_COMPLEX as c_ushort;
202}
203
204/// Initalizes a CIF (Call Interface) with the given ABI
205/// and types.
206///
207/// We need to initialize a CIF before we can use it to call a function
208/// or create a closure. This function lets us specify the calling
209/// convention to use and the argument and result types. For varargs
210/// CIF initialization, see [`prep_cif_var`](fn.prep_cif_var.html).
211///
212///
213/// # Safety
214///
215/// The CIF `cif` retains references to `rtype` and `atypes`, so if
216/// they are no longer live when the CIF is used then the behavior is
217/// undefined.
218///
219/// # Arguments
220///
221/// - `cif` — the CIF to initialize
222/// - `abi` — the calling convention to use
223/// - `nargs` — the number of arguments
224/// - `rtype` — the result type
225/// - `atypes` — the argument types (length must be at least `nargs`)
226///
227/// # Result
228///
229/// `Ok(())` for success or `Err(e)` for failure.
230///
231/// # Examples
232///
233/// ```
234/// use deno_libffi::low::*;
235///
236/// let mut args: [*mut ffi_type; 2] = unsafe {
237///     [ &mut types::sint32,
238///       &mut types::uint64 ]
239/// };
240/// let mut cif: ffi_cif = Default::default();
241///
242/// unsafe {
243///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 2,
244///              &mut types::pointer, args.as_mut_ptr())
245/// }.unwrap();
246/// ```
247pub unsafe fn prep_cif(
248    cif: *mut ffi_cif,
249    abi: ffi_abi,
250    nargs: usize,
251    rtype: *mut ffi_type,
252    atypes: *mut *mut ffi_type,
253) -> Result<()> {
254    let status = raw::ffi_prep_cif(cif, abi, nargs as c_uint, rtype, atypes);
255    status_to_result(status, ())
256}
257
258/// Initalizes a CIF (Call Interface) for a varargs function.
259///
260/// We need to initialize a CIF before we can use it to call a function
261/// or create a closure. This function lets us specify the calling
262/// convention to use and the argument and result types. For non-varargs
263/// CIF initialization, see [`prep_cif`](fn.prep_cif.html).
264///
265/// # Safety
266///
267/// The CIF `cif` retains references to `rtype` and `atypes`, so if
268/// they are no longer live when the CIF is used then the behavior is
269/// undefined.
270///
271/// # Arguments
272///
273/// - `cif` — the CIF to initialize
274/// - `abi` — the calling convention to use
275/// - `nfixedargs` — the number of fixed arguments
276/// - `ntotalargs` — the total number of arguments, including fixed and
277///    var args
278/// - `rtype` — the result type
279/// - `atypes` — the argument types (length must be at least `nargs`)
280///
281/// # Result
282///
283/// `Ok(())` for success or `Err(e)` for failure.
284///
285pub unsafe fn prep_cif_var(
286    cif: *mut ffi_cif,
287    abi: ffi_abi,
288    nfixedargs: usize,
289    ntotalargs: usize,
290    rtype: *mut ffi_type,
291    atypes: *mut *mut ffi_type,
292) -> Result<()> {
293    let status = raw::ffi_prep_cif_var(
294        cif,
295        abi,
296        nfixedargs as c_uint,
297        ntotalargs as c_uint,
298        rtype,
299        atypes,
300    );
301    status_to_result(status, ())
302}
303
304/// Calls a C function as specified by a CIF.
305///
306/// # Arguments
307///
308/// * `cif` — describes the argument and result types and the calling
309///           convention
310/// * `fun` — the function to call
311/// * `args` — the arguments to pass to `fun`
312///
313/// # Result
314///
315/// The result of calling `fun` with `args`.
316///
317/// # Examples
318///
319/// ```
320/// use std::os::raw::c_void;
321/// use deno_libffi::low::*;
322///
323/// extern "C" fn c_function(a: u64, b: u64) -> u64 { a + b }
324///
325/// let result = unsafe {
326///     let mut args: Vec<*mut ffi_type> = vec![ &mut types::uint64,
327///                                              &mut types::uint64 ];
328///     let mut cif: ffi_cif = Default::default();
329///
330///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 2,
331///              &mut types::uint64, args.as_mut_ptr()).unwrap();
332///
333///     call(&mut cif, CodePtr(c_function as *mut _),
334///          vec![ &mut 4u64 as *mut _ as *mut c_void,
335///                &mut 5u64 as *mut _ as *mut c_void ].as_mut_ptr())
336/// };
337///
338/// assert_eq!(9, result);
339/// ```
340pub unsafe fn call<R>(cif: *mut ffi_cif, fun: CodePtr, args: *mut *mut c_void) -> R {
341    let mut result = mem::MaybeUninit::<R>::uninit();
342    raw::ffi_call(
343        cif,
344        Some(*fun.as_safe_fun()),
345        result.as_mut_ptr() as *mut c_void,
346        args,
347    );
348    result.assume_init()
349}
350
351/// Allocates a closure.
352///
353/// Returns a pair of the writable closure object and the function
354/// pointer for calling it. The former acts as a handle to the closure,
355/// and is used to configure and free it. The latter is the code pointer
356/// used to invoke the closure. Before it can be invoked, it must be
357/// initialized with [`prep_closure`](fn.prep_closure.html) and
358/// [`prep_closure_mut`](fn.prep_closure_mut.html). The closure must be
359/// deallocated using [`closure_free`](fn.closure_free.html), after
360/// which point the code pointer should not be used.
361///
362/// # Examples
363///
364/// ```
365/// use deno_libffi::low::*;
366///
367/// let (closure_handle, code_ptr) = closure_alloc();
368/// ```
369pub fn closure_alloc() -> (*mut ffi_closure, CodePtr) {
370    unsafe {
371        let mut code_pointer = mem::MaybeUninit::<*mut c_void>::uninit();
372        let closure =
373            raw::ffi_closure_alloc(mem::size_of::<ffi_closure>(), code_pointer.as_mut_ptr());
374        (
375            closure as *mut ffi_closure,
376            CodePtr::from_ptr(code_pointer.assume_init()),
377        )
378    }
379}
380
381/// Frees a closure.
382///
383/// Closures allocated with [`closure_alloc`](fn.closure_alloc.html)
384/// must be deallocated with `closure_free`.
385///
386/// # Examples
387///
388/// ```
389/// use deno_libffi::low::*;
390///
391/// let (closure_handle, code_ptr) = closure_alloc();
392///
393/// // ...
394///
395/// unsafe {
396///     closure_free(closure_handle);
397/// }
398/// ```
399pub unsafe fn closure_free(closure: *mut ffi_closure) {
400    raw::ffi_closure_free(closure as *mut c_void);
401}
402
403/// The type of function called by a closure.
404///
405/// `U` is the type of the user data captured by the closure and passed
406/// to the callback, and `R` is the type of the result. The parameters
407/// are not typed, since they are passed as a C array of `void*`.
408pub type Callback<U, R> =
409    unsafe extern "C" fn(cif: &ffi_cif, result: &mut R, args: *const *const c_void, userdata: &U);
410
411/// The type of function called by a mutable closure.
412///
413/// `U` is the type of the user data captured by the closure and passed
414/// to the callback, and `R` is the type of the result. The parameters
415/// are not typed, since they are passed as a C array of `void*`.
416pub type CallbackMut<U, R> = unsafe extern "C" fn(
417    cif: &ffi_cif,
418    result: &mut R,
419    args: *const *const c_void,
420    userdata: &mut U,
421);
422
423/// The callback type expected by `raw::ffi_prep_closure_loc`.
424pub type RawCallback = unsafe extern "C" fn(
425    cif: *mut ffi_cif,
426    result: *mut c_void,
427    args: *mut *mut c_void,
428    userdata: *mut c_void,
429);
430
431/// Initializes a closure with a callback function and userdata.
432///
433/// After allocating a closure with
434/// [`closure_alloc`](fn.closure_alloc.html), it needs to be initialized
435/// with a function `callback` to call and a pointer `userdata` to pass
436/// to it. Invoking the closure’s code pointer will then pass the provided
437/// arguments and the user data pointer to the callback.
438///
439/// For mutable userdata use [`prep_closure_mut`](fn.prep_closure_mut.html).
440///
441/// # Safety
442///
443/// The closure retains a reference to CIF `cif`, so that must
444/// still be live when the closure is used lest undefined behavior
445/// result.
446///
447/// # Arguments
448///
449/// - `closure` — the closure to initialize
450/// - `cif` — the calling convention and types for calling the closure
451/// - `callback` — the function that the closure will invoke
452/// - `userdata` — the closed-over value, stored in the closure and
453///    passed to the callback upon invocation
454/// - `code` — the closure’s code pointer, *i.e.*, the second component
455///   returned by [`closure_alloc`](fn.closure_alloc.html).
456///
457/// # Result
458///
459/// `Ok(())` for success or `Err(e)` for failure.
460///
461/// # Examples
462///
463/// ```
464/// use deno_libffi::low::*;
465///
466/// use std::mem;
467/// use std::os::raw::c_void;
468///
469/// unsafe extern "C" fn callback(_cif: &ffi_cif,
470///                               result: &mut u64,
471///                               args: *const *const c_void,
472///                               userdata: &u64)
473/// {
474///     let args: *const &u64 = mem::transmute(args);
475///     *result = **args + *userdata;
476/// }
477///
478/// fn twice(f: extern "C" fn(u64) -> u64, x: u64) -> u64 {
479///     f(f(x))
480/// }
481///
482/// unsafe {
483///     let mut cif: ffi_cif = Default::default();
484///     let mut args = [&mut types::uint64 as *mut _];
485///     let mut userdata: u64 = 5;
486///
487///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 1, &mut types::uint64,
488///              args.as_mut_ptr()).unwrap();
489///
490///     let (closure, code) = closure_alloc();
491///     let add5: extern "C" fn(u64) -> u64 = mem::transmute(code);
492///
493///     prep_closure(closure,
494///                  &mut cif,
495///                  callback,
496///                  &mut userdata,
497///                  CodePtr(add5 as *mut _)).unwrap();
498///
499///     assert_eq!(11, add5(6));
500///     assert_eq!(12, add5(7));
501///
502///     assert_eq!(22, twice(add5, 12));
503/// }
504/// ```
505pub unsafe fn prep_closure<U, R>(
506    closure: *mut ffi_closure,
507    cif: *mut ffi_cif,
508    callback: Callback<U, R>,
509    userdata: *const U,
510    code: CodePtr,
511) -> Result<()> {
512    let status = raw::ffi_prep_closure_loc(
513        closure,
514        cif,
515        Some(mem::transmute::<Callback<U, R>, RawCallback>(callback)),
516        userdata as *mut c_void,
517        code.as_mut_ptr(),
518    );
519    status_to_result(status, ())
520}
521
522/// Initializes a mutable closure with a callback function and (mutable)
523/// userdata.
524///
525/// After allocating a closure with
526/// [`closure_alloc`](fn.closure_alloc.html), it needs to be initialized
527/// with a function `callback` to call and a pointer `userdata` to pass
528/// to it. Invoking the closure’s code pointer will then pass the provided
529/// arguments and the user data pointer to the callback.
530///
531/// For immutable userdata use [`prep_closure`](fn.prep_closure.html).
532///
533/// # Safety
534///
535/// The closure retains a reference to CIF `cif`, so that must
536/// still be live when the closure is used lest undefined behavior
537/// result.
538///
539/// # Arguments
540///
541/// - `closure` — the closure to initialize
542/// - `cif` — the calling convention and types for calling the closure
543/// - `callback` — the function that the closure will invoke
544/// - `userdata` — the closed-over value, stored in the closure and
545///    passed to the callback upon invocation
546/// - `code` — the closure’s code pointer, *i.e.*, the second component
547///   returned by [`closure_alloc`](fn.closure_alloc.html).
548///
549/// # Result
550///
551/// `Ok(())` for success or `Err(e)` for failure.
552///
553/// # Examples
554///
555/// ```
556/// use deno_libffi::low::*;
557///
558/// use std::mem;
559/// use std::os::raw::c_void;
560///
561/// unsafe extern "C" fn callback(_cif: &ffi_cif,
562///                               result: &mut u64,
563///                               args: *const *const c_void,
564///                               userdata: &mut u64)
565/// {
566///     let args: *const &u64 = mem::transmute(args);
567///     *result = *userdata;
568///     *userdata += **args;
569/// }
570///
571/// fn twice(f: extern "C" fn(u64) -> u64, x: u64) -> u64 {
572///     f(f(x))
573/// }
574///
575/// unsafe {
576///     let mut cif: ffi_cif = Default::default();
577///     let mut args = [&mut types::uint64 as *mut _];
578///     let mut userdata: u64 = 5;
579///
580///     prep_cif(&mut cif, ffi_abi_FFI_DEFAULT_ABI, 1, &mut types::uint64,
581///              args.as_mut_ptr()).unwrap();
582///
583///     let (closure, code) = closure_alloc();
584///     let add5: extern "C" fn(u64) -> u64 = mem::transmute(code);
585///
586///     prep_closure_mut(closure,
587///                      &mut cif,
588///                      callback,
589///                      &mut userdata,
590///                      CodePtr(add5 as *mut _)).unwrap();
591///
592///     assert_eq!(5, add5(6));
593///     assert_eq!(11, add5(7));
594///
595///     assert_eq!(19, twice(add5, 1));
596/// }
597/// ```
598pub unsafe fn prep_closure_mut<U, R>(
599    closure: *mut ffi_closure,
600    cif: *mut ffi_cif,
601    callback: CallbackMut<U, R>,
602    userdata: *mut U,
603    code: CodePtr,
604) -> Result<()> {
605    let status = raw::ffi_prep_closure_loc(
606        closure,
607        cif,
608        Some(mem::transmute::<CallbackMut<U, R>, RawCallback>(callback)),
609        userdata as *mut c_void,
610        code.as_mut_ptr(),
611    );
612    status_to_result(status, ())
613}