115 lines
4.4 KiB
Rust
115 lines
4.4 KiB
Rust
#[macro_export]
|
|
macro_rules! load_function_ptrs {
|
|
($struct_name: ident, { $($name: ident($($param_n: ident: $param_ty: ty),*) -> $ret: ty,)+ }) => (
|
|
paste::item! {
|
|
$(
|
|
#[allow(non_camel_case_types)]
|
|
pub type [<PFN_ $name>] = extern "system" fn($($param_ty),*) -> $ret;
|
|
)+
|
|
|
|
pub struct $struct_name {
|
|
$(
|
|
pub $name: [<PFN_ $name>],
|
|
)+
|
|
}
|
|
|
|
impl $struct_name {
|
|
pub fn load<F>(mut f: F) -> $struct_name
|
|
where F: FnMut(&std::ffi::CStr) -> *const std::os::raw::c_void
|
|
{
|
|
$struct_name {
|
|
$(
|
|
$name: unsafe {
|
|
let dummy: *const std::ffi::c_void = std::ptr::null();
|
|
|
|
let name = std::ffi::CStr::from_bytes_with_nul_unchecked(concat!(stringify!($name), "\0").as_bytes());
|
|
let val = f(name);
|
|
|
|
if val.is_null() {
|
|
println!("failed loading {}", stringify!($name));
|
|
std::mem::transmute(dummy)
|
|
} else {
|
|
std::mem::transmute(val)
|
|
}
|
|
},
|
|
)+
|
|
}
|
|
}
|
|
|
|
$(
|
|
#[inline]
|
|
pub unsafe fn $name(&self $(, $param_n: $param_ty)*) -> $ret {
|
|
let ptr = self.$name;
|
|
ptr($($param_n),*)
|
|
}
|
|
)+
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! load_function_ptrs_from_lib {
|
|
($struct_name: ident, $library: expr, { $($name: ident($($param_n: ident: $param_ty: ty),*) -> $ret: ty,)+ }) => (
|
|
paste::item! {
|
|
$(
|
|
#[allow(non_camel_case_types)]
|
|
pub type [<PFN_ $name>] = extern "system" fn($($param_ty),*) -> $ret;
|
|
)+
|
|
|
|
pub struct $struct_name {
|
|
pub _lib: Option<shared_library::dynamic_library::DynamicLibrary>,
|
|
|
|
$(
|
|
pub $name: [<PFN_ $name>],
|
|
)+
|
|
}
|
|
|
|
impl $struct_name {
|
|
pub fn load() -> anyhow::Result<$struct_name> {
|
|
let lib = match shared_library::dynamic_library::DynamicLibrary::open(Some(std::path::Path::new($library))) {
|
|
Ok(lib) => lib,
|
|
Err(err) => {
|
|
return Err(anyhow::Error::msg(format!(
|
|
"Failed loading library ({}): {}",
|
|
$library,
|
|
err
|
|
)))
|
|
}
|
|
};
|
|
|
|
Ok($struct_name {
|
|
$(
|
|
$name: unsafe {
|
|
extern "system" fn $name($(_: $param_ty),*) { panic!("function pointer `{}` not loaded", stringify!($name)) }
|
|
let name = std::ffi::CStr::from_bytes_with_nul_unchecked(concat!(stringify!($name), "\0").as_bytes());
|
|
let val: *const std::os::raw::c_void = {
|
|
let str_name = name.to_str().expect("can't convert CStr");
|
|
lib.symbol(str_name)
|
|
.unwrap_or_else(|_| panic!("failed getting {}", str_name))
|
|
};
|
|
|
|
if val.is_null() {
|
|
println!("failed loading {}", stringify!($name));
|
|
std::mem::transmute($name as *const ())
|
|
} else {
|
|
std::mem::transmute(val)
|
|
}
|
|
},
|
|
)+
|
|
|
|
_lib: Some(lib),
|
|
})
|
|
}
|
|
|
|
$(
|
|
#[inline]
|
|
pub unsafe fn $name(&self $(, $param_n: $param_ty)*) -> $ret {
|
|
let ptr = self.$name;
|
|
ptr($($param_n),*)
|
|
}
|
|
)+
|
|
}
|
|
}
|
|
)
|
|
}
|