libffi2/middle/
mod.rs

1//! Middle layer providing a somewhat safer (but still quite unsafe)
2//! API.
3//!
4//! The main idea of the middle layer is to wrap types [`low::ffi_cif`]
5//! and [`low::ffi_closure`] as [`Cif`] and [`Closure`], respectively,
6//! so that their resources are managed properly. However, calling a
7//! function via a CIF or closure is still unsafe because argument types
8//! aren’t checked. See the [`high`](crate::high) layer for closures
9//! with type-checked arguments.
10
11use std::any::Any;
12use std::marker::PhantomData;
13use std::os::raw::c_void;
14
15use crate::low;
16pub use crate::low::{ffi_abi as FfiAbi, ffi_abi_FFI_DEFAULT_ABI, Callback, CallbackMut, CodePtr};
17
18mod util;
19
20mod types;
21pub use types::Type;
22
23mod builder;
24pub use builder::Builder;
25
26/// Contains an untyped pointer to a function argument.
27///
28/// When calling a function via a [CIF](Cif), each argument
29/// must be passed as a C `void*`. Wrapping the argument in the [`Arg`]
30/// struct accomplishes the necessary coercion.
31#[derive(Clone, Debug)]
32#[repr(C)]
33pub struct Arg(*mut c_void);
34
35impl Arg {
36    /// Coerces an argument reference into the [`Arg`] type.
37    ///
38    /// This is used to wrap each argument pointer before passing them
39    /// to [`Cif::call`].
40    pub fn new<T>(r: &T) -> Self {
41        Arg(r as *const T as *mut c_void)
42    }
43}
44
45/// Coerces an argument reference into the [`Arg`] type.
46///
47/// This is used to wrap each argument pointer before passing them
48/// to [`Cif::call`]. (This is the same as [`Arg::new`]).
49pub fn arg<T>(r: &T) -> Arg {
50    Arg::new(r)
51}
52
53/// Describes the calling convention and types for calling a function.
54///
55/// This is the middle layer’s wrapping of the [`low`](crate::low) and
56/// [`raw`](crate::raw) layers’ [`low::ffi_cif`]. An initialized CIF
57/// contains references to an array of argument types and a result type,
58/// each of which may be allocated on the heap. `Cif` manages the memory
59/// of those referenced objects.
60///
61/// Construct with [`Cif::new`].
62///
63/// # Examples
64///
65/// ```
66/// extern "C" fn add(x: f64, y: &f64) -> f64 {
67///     return x + y;
68/// }
69///
70/// use libffi::middle::*;
71///
72/// let args = vec![Type::f64(), Type::pointer()];
73/// let cif = Cif::new(args.into_iter(), Type::f64());
74///
75/// let n = unsafe { cif.call(CodePtr(add as *mut _), &[arg(&5f64), arg(&&6f64)]) };
76/// assert_eq!(11f64, n);
77/// ```
78#[derive(Debug)]
79pub struct Cif {
80    cif: low::ffi_cif,
81    args: types::TypeArray,
82    result: Type,
83}
84
85// To clone a Cif we need to clone the types and then make sure the new
86// ffi_cif refers to the clones of the types.
87impl Clone for Cif {
88    fn clone(&self) -> Self {
89        let mut copy = Cif {
90            cif: self.cif,
91            args: self.args.clone(),
92            result: self.result.clone(),
93        };
94
95        copy.cif.arg_types = copy.args.as_raw_ptr();
96        copy.cif.rtype = copy.result.as_raw_ptr();
97
98        copy
99    }
100}
101
102impl Cif {
103    /// Creates a new [CIF](Cif) for the given argument and result
104    /// types.
105    ///
106    /// Takes ownership of the argument and result [`Type`]s, because
107    /// the resulting [`Cif`] retains references to them. Defaults to
108    /// the platform’s default calling convention; this can be adjusted
109    /// using [`Cif::set_abi`].
110    pub fn new<I>(args: I, result: Type) -> Self
111    where
112        I: IntoIterator<Item = Type>,
113        I::IntoIter: ExactSizeIterator<Item = Type>,
114    {
115        let args = args.into_iter();
116        let nargs = args.len();
117        let args = types::TypeArray::new(args);
118        let mut cif: low::ffi_cif = Default::default();
119
120        unsafe {
121            low::prep_cif(
122                &mut cif,
123                low::ffi_abi_FFI_DEFAULT_ABI,
124                nargs,
125                result.as_raw_ptr(),
126                args.as_raw_ptr(),
127            )
128        }
129        .expect("low::prep_cif");
130
131        // Note that cif retains references to args and result,
132        // which is why we hold onto them here.
133        Cif { cif, args, result }
134    }
135
136    /// Calls a function with the given arguments.
137    ///
138    /// In particular, this method invokes function `fun` passing it
139    /// arguments `args`, and returns the result.
140    ///
141    /// # Safety
142    ///
143    /// There is no checking that the calling convention and types
144    /// in the `Cif` match the actual calling convention and types of
145    /// `fun`, nor that they match the types of `args`.
146    pub unsafe fn call<R>(&self, fun: CodePtr, args: &[Arg]) -> R {
147        assert_eq!(
148            self.cif.nargs as usize,
149            args.len(),
150            "Cif::call: passed wrong number of arguments"
151        );
152
153        low::call::<R>(
154            &self.cif as *const _ as *mut _,
155            fun,
156            args.as_ptr() as *mut *mut c_void,
157        )
158    }
159
160    /// Sets the CIF to use the given calling convention.
161    pub fn set_abi(&mut self, abi: FfiAbi) {
162        self.cif.abi = abi;
163    }
164
165    /// Gets a raw pointer to the underlying [`low::ffi_cif`].
166    ///
167    /// This can be used for passing a `middle::Cif` to functions from the
168    /// [`low`](crate::low) and [`raw`](crate::raw) modules.
169    pub fn as_raw_ptr(&self) -> *mut low::ffi_cif {
170        &self.cif as *const _ as *mut _
171    }
172}
173
174/// Represents a closure callable from C.
175///
176/// A libffi closure captures a `void*` (“userdata”) and passes it to a
177/// callback when the code pointer (obtained via [`Closure::code_ptr`])
178/// is invoked. Lifetype parameter `'a` ensures that the closure does
179/// not outlive the userdata.
180///
181/// Construct with [`Closure::new`] and [`Closure::new_mut`].
182///
183/// # Examples
184///
185/// In this example we turn a Rust lambda into a C function. We first
186/// define function `lambda_callback`, which will be called by libffi
187/// when the closure is called. The callback function takes four
188/// arguments: a CIF describing its arguments, a pointer for where to
189/// store its result, a pointer to an array of pointers to its
190/// arguments, and a userdata pointer. In this ase, the Rust closure
191/// value `lambda` is passed as userdata to `lambda_callback`, which
192/// then invokes it.
193///
194/// ```
195/// use std::mem;
196/// use std::os::raw::c_void;
197///
198/// use libffi::middle::*;
199/// use libffi::low;
200///
201/// unsafe extern "C" fn lambda_callback<F: Fn(u64, u64) -> u64>(
202///     _cif: &low::ffi_cif,
203///     result: &mut u64,
204///     args: *const *const c_void,
205///     userdata: &F)
206/// {
207///     let args = args as *const &u64;
208///     let arg1 = **args.offset(0);
209///     let arg2 = **args.offset(1);
210///
211///     *result = userdata(arg1, arg2);
212/// }
213///
214/// let cif = Cif::new(vec![Type::u64(), Type::u64()].into_iter(),
215///                    Type::u64());
216/// let lambda = |x: u64, y: u64| x + y;
217/// let closure = Closure::new(cif, lambda_callback, &lambda);
218///
219/// let fun: &extern "C" fn(u64, u64) -> u64 = unsafe {
220///     closure.instantiate_code_ptr()
221/// };
222///
223/// assert_eq!(11, fun(5, 6));
224/// assert_eq!(12, fun(5, 7));
225/// ```
226#[derive(Debug)]
227pub struct Closure<'a> {
228    _cif: Box<Cif>,
229    alloc: *mut low::ffi_closure,
230    code: CodePtr,
231    _marker: PhantomData<&'a ()>,
232}
233
234impl<'a> Drop for Closure<'a> {
235    fn drop(&mut self) {
236        unsafe {
237            low::closure_free(self.alloc);
238        }
239    }
240}
241
242impl<'a> Closure<'a> {
243    /// Creates a new closure with immutable userdata.
244    ///
245    /// # Arguments
246    ///
247    /// - `cif` — describes the calling convention and argument and
248    ///   result types
249    /// - `callback` — the function to call when the closure is invoked
250    /// - `userdata` — the pointer to pass to `callback` along with the
251    ///   arguments when the closure is called
252    ///
253    /// # Result
254    ///
255    /// The new closure.
256    pub fn new<U, R>(cif: Cif, callback: Callback<U, R>, userdata: &'a U) -> Self {
257        let cif = Box::new(cif);
258        let (alloc, code) = low::closure_alloc();
259
260        unsafe {
261            low::prep_closure(
262                alloc,
263                cif.as_raw_ptr(),
264                callback,
265                userdata as *const U,
266                code,
267            )
268            .unwrap();
269        }
270
271        Closure {
272            _cif: cif,
273            alloc,
274            code,
275            _marker: PhantomData,
276        }
277    }
278
279    /// Creates a new closure with mutable userdata.
280    ///
281    /// # Arguments
282    ///
283    /// - `cif` — describes the calling convention and argument and
284    ///   result types
285    /// - `callback` — the function to call when the closure is invoked
286    /// - `userdata` — the pointer to pass to `callback` along with the
287    ///   arguments when the closure is called
288    ///
289    /// # Result
290    ///
291    /// The new closure.
292    pub fn new_mut<U, R>(cif: Cif, callback: CallbackMut<U, R>, userdata: &'a mut U) -> Self {
293        let cif = Box::new(cif);
294        let (alloc, code) = low::closure_alloc();
295
296        unsafe {
297            low::prep_closure_mut(alloc, cif.as_raw_ptr(), callback, userdata as *mut U, code)
298                .unwrap();
299        }
300
301        Closure {
302            _cif: cif,
303            alloc,
304            code,
305            _marker: PhantomData,
306        }
307    }
308
309    /// Obtains the callable code pointer for a closure.
310    ///
311    /// # Safety
312    ///
313    /// The result needs to be transmuted to the correct type before
314    /// it can be called. If the type is wrong then undefined behavior
315    /// will result.
316    pub fn code_ptr(&self) -> &unsafe extern "C" fn() {
317        self.code.as_fun()
318    }
319
320    /// Transmutes the callable code pointer for a closure to a reference
321    /// to any type. This is intended to be used to transmute it to its
322    /// correct function type in order to call it.
323    ///
324    /// # Safety
325    ///
326    /// This method allows transmuting to a reference to *any* sized type,
327    /// and cannot check whether the code pointer actually has that type.
328    /// If the type is wrong then undefined behavior will result.
329    pub unsafe fn instantiate_code_ptr<T>(&self) -> &T {
330        self.code.as_any_ref_()
331    }
332}
333
334/// The type of callback invoked by a [`ClosureOnce`].
335pub type CallbackOnce<U, R> = CallbackMut<Option<U>, R>;
336
337/// A closure that owns needs-drop data.
338///
339/// This allows the closure’s callback to take ownership of the data, in
340/// which case the userdata will be gone if called again.
341#[derive(Debug)]
342pub struct ClosureOnce {
343    alloc: *mut low::ffi_closure,
344    code: CodePtr,
345    _cif: Box<Cif>,
346    _userdata: Box<dyn Any>,
347}
348
349impl Drop for ClosureOnce {
350    fn drop(&mut self) {
351        unsafe {
352            low::closure_free(self.alloc);
353        }
354    }
355}
356
357impl ClosureOnce {
358    /// Creates a new closure with owned userdata.
359    ///
360    /// # Arguments
361    ///
362    /// - `cif` — describes the calling convention and argument and
363    ///   result types
364    /// - `callback` — the function to call when the closure is invoked
365    /// - `userdata` — the value to pass to `callback` along with the
366    ///   arguments when the closure is called
367    ///
368    /// # Result
369    ///
370    /// The new closure.
371    pub fn new<U: Any, R>(cif: Cif, callback: CallbackOnce<U, R>, userdata: U) -> Self {
372        let _cif = Box::new(cif);
373        let _userdata = Box::new(Some(userdata)) as Box<dyn Any>;
374        let (alloc, code) = low::closure_alloc();
375
376        assert!(!alloc.is_null(), "closure_alloc: returned null");
377
378        {
379            let borrow = _userdata.downcast_ref::<Option<U>>().unwrap();
380            unsafe {
381                low::prep_closure_mut(
382                    alloc,
383                    _cif.as_raw_ptr(),
384                    callback,
385                    borrow as *const _ as *mut _,
386                    code,
387                )
388                .unwrap();
389            }
390        }
391
392        ClosureOnce {
393            alloc,
394            code,
395            _cif,
396            _userdata,
397        }
398    }
399
400    /// Obtains the callable code pointer for a closure.
401    ///
402    /// # Safety
403    ///
404    /// The result needs to be transmuted to the correct type before
405    /// it can be called. If the type is wrong then undefined behavior
406    /// will result.
407    pub fn code_ptr(&self) -> &unsafe extern "C" fn() {
408        self.code.as_fun()
409    }
410
411    /// Transmutes the callable code pointer for a closure to a reference
412    /// to any type. This is intended to be used to transmute it to its
413    /// correct function type in order to call it.
414    ///
415    /// # Safety
416    ///
417    /// This method allows transmuting to a reference to *any* sized type,
418    /// and cannot check whether the code pointer actually has that type.
419    /// If the type is wrong then undefined behavior will result.
420    pub unsafe fn instantiate_code_ptr<T>(&self) -> &T {
421        self.code.as_any_ref_()
422    }
423}
424
425#[cfg(test)]
426mod test {
427    use super::*;
428    use crate::low;
429    use std::os::raw::c_void;
430
431    #[test]
432    fn call() {
433        let cif = Cif::new(vec![Type::i64(), Type::i64()].into_iter(), Type::i64());
434        let f = |m: i64, n: i64| -> i64 {
435            unsafe { cif.call(CodePtr(add_it as *mut c_void), &[arg(&m), arg(&n)]) }
436        };
437
438        assert_eq!(12, f(5, 7));
439        assert_eq!(13, f(6, 7));
440        assert_eq!(15, f(8, 7));
441    }
442
443    extern "C" fn add_it(n: i64, m: i64) -> i64 {
444        n + m
445    }
446
447    #[test]
448    fn closure() {
449        let cif = Cif::new(vec![Type::u64()].into_iter(), Type::u64());
450        let env: u64 = 5;
451        let closure = Closure::new(cif, callback, &env);
452
453        let fun: &extern "C" fn(u64) -> u64 = unsafe { closure.instantiate_code_ptr() };
454
455        assert_eq!(11, fun(6));
456        assert_eq!(12, fun(7));
457    }
458
459    unsafe extern "C" fn callback(
460        _cif: &low::ffi_cif,
461        result: &mut u64,
462        args: *const *const c_void,
463        userdata: &u64,
464    ) {
465        let args = args as *const &u64;
466        *result = **args + *userdata;
467    }
468
469    #[test]
470    fn rust_lambda() {
471        let cif = Cif::new(vec![Type::u64(), Type::u64()].into_iter(), Type::u64());
472        let env = |x: u64, y: u64| x + y;
473        let closure = Closure::new(cif, callback2, &env);
474
475        let fun: &extern "C" fn(u64, u64) -> u64 = unsafe { closure.instantiate_code_ptr() };
476
477        assert_eq!(11, fun(5, 6));
478    }
479
480    unsafe extern "C" fn callback2<F: Fn(u64, u64) -> u64>(
481        _cif: &low::ffi_cif,
482        result: &mut u64,
483        args: *const *const c_void,
484        userdata: &F,
485    ) {
486        let args = args as *const &u64;
487        let arg1 = **args.offset(0);
488        let arg2 = **args.offset(1);
489
490        *result = userdata(arg1, arg2);
491    }
492
493    #[test]
494    fn clone_cif() {
495        let cif = Cif::new(
496            vec![
497                Type::structure(vec![
498                    Type::structure(vec![Type::u64(), Type::u8(), Type::f64()]),
499                    Type::i8(),
500                    Type::i64(),
501                ]),
502                Type::u64(),
503            ]
504            .into_iter(),
505            Type::u64(),
506        );
507        let clone_cif = cif.clone();
508
509        unsafe {
510            let args = std::slice::from_raw_parts(cif.cif.arg_types, cif.cif.nargs as usize);
511            let struct_arg = args
512                .first()
513                .expect("CIF arguments slice was empty")
514                .as_ref()
515                .expect("CIF first argument was null");
516            // Get slice of length 1 to get the first element
517            let struct_size = struct_arg.size;
518            let struct_parts = std::slice::from_raw_parts(struct_arg.elements, 1);
519            let substruct_size = struct_parts
520                .first()
521                .expect("CIF struct argument's elements slice was empty")
522                .as_ref()
523                .expect("CIF struct argument's first element was null")
524                .size;
525
526            let clone_args =
527                std::slice::from_raw_parts(clone_cif.cif.arg_types, clone_cif.cif.nargs as usize);
528            let clone_struct_arg = clone_args
529                .first()
530                .expect("CIF arguments slice was empty")
531                .as_ref()
532                .expect("CIF first argument was null");
533            // Get slice of length 1 to get the first element
534            let clone_struct_size = clone_struct_arg.size;
535            let clone_struct_parts = std::slice::from_raw_parts(clone_struct_arg.elements, 1);
536            let clone_substruct_size = clone_struct_parts
537                .first()
538                .expect("Cloned CIF struct argument's elements slice was empty")
539                .as_ref()
540                .expect("Cloned CIF struct argument's first element was null")
541                .size;
542
543            assert_eq!(struct_size, clone_struct_size);
544            assert_eq!(substruct_size, clone_substruct_size);
545        }
546    }
547}