1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
//! Simple dynamic calls. //! //! This API allows us to call a code pointer with an array of //! arguments, using libffi to set up the call. //! //! # Examples //! //! ``` //! extern "C" fn hypot(x: f32, y: f32) -> f32 { //! (x * x + y * y).sqrt() //! } //! //! use libffi::ffi_call; //! //! let result = unsafe { ffi_call!{ hypot(3f32, 4f32) -> f32 } }; //! //! assert!((result - 5f32).abs() < 0.0001); //! ``` use std::marker::PhantomData; use crate::middle; pub use middle::CodePtr; /// Encapsulates an argument with its type information. /// /// In order to set up calls using [`call`](index.html#method.call), we /// need to wrap (a reference to) each argument in an `Arg`. The usual /// way to do this is with function [`arg`](fn.arg.html). #[derive(Clone, Debug)] pub struct Arg<'a> { // There should be some type T such that type_ is the middle-layer // value of Type<T> and value is T::reify(). type_: middle::Type, value: middle::Arg, _marker: PhantomData<&'a ()>, } impl<'a> Arg<'a> { /// Wraps an argument reference for passing to `high::call::call`. /// /// For a shorter alias of the same, see /// [`high::call::arg`](fn.arg.html). pub fn new<T: super::CType>(arg: &'a T) -> Self { Arg { type_: T::reify().into_middle(), value: middle::Arg::new(arg), _marker: PhantomData, } } } /// Constructs an [`Arg`](struct.Arg.html) for passing to /// [`call`](fn.call.html). pub fn arg<T: super::CType>(arg: &T) -> Arg { Arg::new(arg) } /// Performs a dynamic call to a C function. /// /// To reduce boilerplate, see [`ffi_call!`](../../macro.ffi_call!.html). /// /// # Examples /// /// ``` /// extern "C" fn hypot(x: f32, y: f32) -> f32 { /// (x * x + y * y).sqrt() /// } /// /// use libffi::high::call::*; /// /// let result = unsafe { /// call::<f32>(CodePtr(hypot as *mut _), &[arg(&3f32), arg(&4f32)]) /// }; /// /// assert!((result - 5f32).abs() < 0.0001); /// ``` pub unsafe fn call<R: super::CType>(fun: CodePtr, args: &[Arg]) -> R { let types = args.iter().map(|arg| arg.type_.clone()); let cif = middle::Cif::new(types, R::reify().into_middle()); let values = args.iter().map(|arg| arg.value.clone()) .collect::<Vec<_>>(); cif.call(fun, &values) } /// Performs a dynamic call to a C function. /// /// This macro provides sugar for `call::arg` and `call::call`. For more /// control, see [`high::call::call`](high/call/fn.call.html). /// /// # Examples /// /// ``` /// extern "C" fn hypot(x: f32, y: f32) -> f32 { /// (x * x + y * y).sqrt() /// } /// /// use libffi::ffi_call; /// /// let result = unsafe { ffi_call!{ hypot(3f32, 4f32) -> f32 } }; /// /// assert!((result - 5f32).abs() < 0.0001); /// ``` #[macro_export] macro_rules! ffi_call { { ( $fun:expr ) ( $( $arg:expr ),* ) -> $ty:ty } => { $crate::high::call::call::<$ty>( $crate::high::call::CodePtr($fun as *mut _), &[$($crate::high::call::arg(&$arg)),*]) }; { $fun:ident ( $( $arg:expr ),* ) -> $ty:ty } => { ffi_call!{ ($fun)($($arg),*) -> $ty } }; { ( $fun:expr ) ( $( $arg:expr ),* ) } => { ffi_call!{ ($fun)($(arg),*) -> () } }; { $fun:ident ( $( $arg:expr ),* ) } => { ffi_call!{ ($fun)($($arg),*) -> () } }; }