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