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 129 130
//! 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() //! } //! //! # #[macro_use] extern crate libffi; //! # fn main() { //! let result = unsafe { ffi_call!{ hypot(3f32, 4f32) -> f32 } }; //! //! assert!((result - 5f32).abs() < 0.0001); //! # } //! ``` use std::marker::PhantomData; use 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.into_iter().map(|arg| arg.type_.clone()); let cif = middle::Cif::new(types, R::reify().into_middle()); let values = args.into_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() /// } /// /// # #[macro_use] extern crate libffi; /// # fn main() { /// 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),*) -> () } }; }