self.table.extend(other.table);
}
- pub fn define_struct(&mut self, name: &str, atom_fields: Vec<Atom>) {
- let mut fields: Vec<_> = atom_fields.iter().map(|x| self.map_type_ffi(x)).collect();
+ pub fn define_struct(&mut self, name: &str, atom_fields: Vec<Atom>) -> Result<(), FFIError> {
+ let mut fields: Vec<_> = atom_fields
+ .iter()
+ .map(|x| self.map_type_ffi(x))
+ .collect::<Result<_, FFIError>>()?;
fields.push(std::ptr::null_mut::<ffi_type>());
let struct_type = ffi_type {
type_: STRUCT,
atom_fields,
},
);
+ Ok(())
}
- fn map_type_ffi(&mut self, source: &Atom) -> *mut ffi_type {
- match source {
+ fn map_type_ffi(&mut self, source: &Atom) -> Result<*mut ffi_type, FFIError> {
+ Ok(match source {
atom!("sint64") => addr_of_mut!(types::sint64),
atom!("sint32") => addr_of_mut!(types::sint32),
atom!("sint16") => addr_of_mut!(types::sint16),
atom!("f64") => addr_of_mut!(types::double),
struct_name => match self.structs.get_mut(&*struct_name.as_str()) {
Some(ref mut struct_type) => &mut struct_type.ffi_type,
- None => unreachable!(),
+ None => return Err(FFIError::InvalidFFIType),
},
- }
+ })
}
pub(crate) fn load_library(
let symbol_name: CString = CString::new(function.name.clone())?;
let code_ptr: Symbol<*mut c_void> =
library.get(&symbol_name.into_bytes_with_nul())?;
- let mut args: Vec<_> = function.args.iter().map(|x| self.map_type_ffi(x)).collect();
+ let mut args: Vec<_> = function
+ .args
+ .iter()
+ .map(|x| self.map_type_ffi(x))
+ .collect::<Result<_, FFIError>>()?;
let mut cif: ffi_cif = Default::default();
prep_cif(
&mut cif,
ffi_abi_FFI_DEFAULT_ABI,
args.len(),
- self.map_type_ffi(&function.return_value),
+ self.map_type_ffi(&function.return_value)?,
args.as_mut_ptr(),
)
.unwrap();
- let return_struct_name = if (*self.map_type_ffi(&function.return_value)).type_
+ let return_struct_name = if (*self.map_type_ffi(&function.return_value)?).type_
as u32
== libffi::raw::FFI_TYPE_STRUCT
{
FunctionNotFound,
StructNotFound,
}
+
+impl std::fmt::Display for FFIError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ std::fmt::Debug::fmt(self, f)
+ }
+}
+
+impl Error for FFIError {}
// but there is currently no other easy way to get the dynamic library file path as an input into a load_module_test test
std::env::set_var("ffi_return_values_LIB", dynlib_path);
- // FIXME u32 and u64 have an incorrect result
+ // i8- -42,u8-73,i16- -3054,u16-49374,i32- -200211438,u32-3235819520,i64- -859901580039547648,u64- 859901580039547648,f32-3.1415927410125732,f64-6.283185307179586
+ let expected = format!(
+ "i8- {},u8-{},i16- {},u16-{},i32- {},u32-{},i64- {},u64- {},f32-{},f64-{}",
+ -42,
+ 73,
+ -0xBEE,
+ 0xC0DE,
+ -0xBEEFBEE,
+ 0xC0DEB000u32,
+ -0xBEEFBEE5C0DEB00i64,
+ 0xBEEFBEE5C0DEB00u64,
+ std::f32::consts::PI as f64,
+ std::f64::consts::TAU
+ );
+
+ // FIXME all but u8, f32 and f64 are wrong!?!?
load_module_test(
"tests-pl/ffi_return_values.pl",
"i8-214,u8-73,i16-18,u16-222,i32-18,u32-0,i64-0,u64- -4789548415587584,f32-3.1415927410125732,f64-6.283185307179586",