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