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}