/// The foreign function interfaces for the dynamic data mod dynamic_data; /// The foreign function interfaces for that static data mod static_data; /// Helper type for clearer functions. type OwnedPtr = *mut T; /// Helper type for clearer functions. type BorrowedPtr = *const T; /// Generates a basic getter foreign function interface. macro_rules! ffi_arc_getter { ( $type:ty, $func:ident, $returns: ty ) => { paste::paste! { #[no_mangle] extern "C" fn [< $type:snake _ $func >](ptr: ExternPointer>) -> $returns { ptr.as_ref().$func() } } }; } /// Generates a basic getter foreign function interface where the return type is a [`crate::StringKey`]. macro_rules! ffi_arc_stringkey_getter { ( $type:ty, $func:ident ) => { paste::paste! { #[no_mangle] extern "C" fn [< $type:lower _ $func >](ptr: ExternPointer>) -> OwnedPtr { std::ffi::CString::new(ptr.as_ref().$func().str()).unwrap().into_raw() } } }; } /// Generates a foreign function interface for a vec. This generates a length function, and a getter. macro_rules! ffi_vec_value_getters { ( $type:ty, $func:ident, $returns: ty ) => { paste::paste! { #[no_mangle] extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer>) -> usize { ptr.as_ref().$func().len() } #[no_mangle] extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer>, index: usize) -> $returns { *ptr.as_ref().$func().get(index).unwrap() } } }; } /// Generates a foreign function interface for a vec of [`crate::StringKey`]. This generates a /// length function, and a getter. macro_rules! ffi_vec_stringkey_getters { ( $type:ident, $func:ident ) => { paste::paste! { #[no_mangle] extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer>) -> usize { ptr.as_ref().$func().len() } #[no_mangle] extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer>, index: usize) -> OwnedPtr { CString::new(ptr.as_ref().$func().get(index).unwrap().str()).unwrap().into_raw() } } }; } use crate::{ValueIdentifiable, ValueIdentifier}; pub(self) use ffi_arc_getter; pub(self) use ffi_arc_stringkey_getter; pub(self) use ffi_vec_stringkey_getters; pub(self) use ffi_vec_value_getters; use std::mem::transmute; use std::sync::Arc; /// Helper utility class to wrap a pointer for extern functions. #[repr(C)] pub(self) struct ExternPointer { /// The wrapped pointer. ptr: *mut T, } impl ExternPointer { /// Get the internal pointer as reference. pub(self) fn as_ref(&self) -> &T { unsafe { self.ptr .as_ref() .unwrap_or_else(|| panic!("Given pointer of type '{}' was null", std::any::type_name::())) } } /// Get the internal pointer as mutable reference. pub(self) fn as_mut(&mut self) -> &mut T { unsafe { self.ptr .as_mut() .unwrap_or_else(|| panic!("Given pointer of type '{}' was null", std::any::type_name::())) } } } /// Helper utility class to give both the pointer and identifier to a FFI. #[repr(C)] pub(self) struct IdentifiablePointer { /// The wrapped pointer. pub ptr: *const T, /// The identifier of the pointer. pub id: usize, } impl IdentifiablePointer { /// Creates a new IdentifiablePointer. pub(self) fn new(ptr: *const T, id: ValueIdentifier) -> Self { unsafe { Self { ptr, id: transmute(id) } } } } impl From<*mut T> for ExternPointer { fn from(ptr: *mut T) -> Self { ExternPointer { ptr } } } impl From> for IdentifiablePointer> { fn from(v: Arc) -> Self { let id = unsafe { transmute(v.value_identifier()) }; Self { ptr: Box::into_raw(Box::new(v)), id, } } } impl From> for IdentifiablePointer { fn from(v: Box) -> Self { let id = unsafe { transmute(v.value_identifier()) }; Self { ptr: Box::into_raw(v), id, } } } impl From<*const T> for IdentifiablePointer { fn from(v: *const T) -> Self { let id = unsafe { transmute(v.as_ref().unwrap().value_identifier()) }; Self { ptr: v, id } } } impl IdentifiablePointer { /// Returns an identifiable pointer with null as pointer, and 0 as identifier. pub fn none() -> Self { Self { ptr: std::ptr::null(), id: Default::default(), } } }