Initial commit

This commit is contained in:
hodasemi 2023-12-08 20:51:24 +01:00
commit ba6c938a6b
5 changed files with 134 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
Cargo.lock
target/

7
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,7 @@
{
"workbench.colorCustomizations": {
"activityBar.background": "#382B16",
"titleBar.activeBackground": "#4F3D1F",
"titleBar.activeForeground": "#FDFBF9"
}
}

8
Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "library_loader"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

1
src/lib.rs Normal file
View file

@ -0,0 +1 @@
pub mod macros;

115
src/macros.rs Normal file
View file

@ -0,0 +1,115 @@
#[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),*)
}
)+
}
}
)
}