use self::super::libc_sys::{dlclose, dlopen, dlsym, RTLD_LAZY, RTLD_LOCAL};
use std::{ffi::CString, ptr::NonNull};
pub struct ModuleLoader(::std::ptr::NonNull<::std::os::raw::c_void>);
impl ModuleLoader {
pub fn load(path: &str) -> Result<Self, ()> {
let path = CString::new(path).unwrap();
let module = unsafe { dlopen(path.as_ptr(), RTLD_LAZY | RTLD_LOCAL) };
if module.is_null() {
Err(())
} else {
Ok(ModuleLoader(unsafe { NonNull::new_unchecked(module) }))
}
}
pub fn get_symbol<F: Sized>(&self, name: &str) -> Result<F, ()> {
let name = CString::new(name).unwrap();
let symbol = unsafe { dlsym(self.0.as_ptr(), name.as_ptr()) };
if symbol.is_null() {
return Err(());
}
Ok(unsafe { std::mem::transmute_copy::<_, F>(&symbol) })
}
}
impl Drop for ModuleLoader {
fn drop(&mut self) {
unsafe { dlclose(self.0.as_ptr()) };
}
}