Initial commit
This commit is contained in:
commit
ba6c938a6b
5 changed files with 134 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
Cargo.lock
|
||||
|
||||
target/
|
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.background": "#382B16",
|
||||
"titleBar.activeBackground": "#4F3D1F",
|
||||
"titleBar.activeForeground": "#FDFBF9"
|
||||
}
|
||||
}
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal 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
1
src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod macros;
|
115
src/macros.rs
Normal file
115
src/macros.rs
Normal 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),*)
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue