use core::convert::TryInto;
use core::marker::PhantomData;
use crate::middle;
pub use middle::CodePtr;
#[derive(Clone, Debug)]
pub struct Arg<'a> {
type_: middle::Type,
value: middle::Arg,
_marker: PhantomData<&'a ()>,
}
impl<'a> Arg<'a> {
pub fn new<T: super::CType>(arg: &'a T) -> Self {
Arg {
type_: T::reify().into_middle(),
value: middle::Arg::new(arg),
_marker: PhantomData,
}
}
}
pub fn arg<T: super::CType>(arg: &T) -> Arg {
Arg::new(arg)
}
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::<R::RetType>(fun, &values)
.try_into()
.ok()
.unwrap()
}
#[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),*) -> () } };
}