use ::libc::c_void;
use ::std::collections::HashMap;
use ::std::ffi::CString;
pub struct Library {
pub(crate) handle: *mut c_void,
pub(crate) name: String,
pub(crate) table: HashMap<String, *mut c_void>,
}
impl Library {
pub unsafe fn handle(&self) -> &*mut c_void {
&self.handle
}
pub unsafe fn table(&self) -> &HashMap<String, *mut c_void> {
&self.table
}
pub fn name(&self) -> String {
self.name.clone()
}
pub fn sym<T>(&mut self, name: String) -> Option<Box<T>> {
if self.table.contains_key(&name) {
let gotten = self.table.get(&name);
unsafe {
let gotten = Box::from_raw(*gotten.unwrap() as *mut T);
return Some(gotten)
}
}
if self.handle.is_null() {
return None
}
let name_c = CString::new(name.as_str());
if name_c.is_err() {
return None
}
let name_c = name_c.unwrap();
let sym: Box<T>;
unsafe {
let sym_c: *mut ::libc::c_void;
if name.is_empty() {
let name_c: *const ::libc::c_char = ::std::ptr::null();
sym_c = ::libc::dlsym(self.handle, name_c);
} else {
sym_c = ::libc::dlsym(self.handle, name_c.as_ptr());
}
sym = Box::from_raw(sym_c as *mut T);
self.table.insert(name, sym_c);
}
Some(sym)
}
pub fn open(name: String, flags: ::RtldValue, closure: fn(lib: Library)) -> bool {
let cstr = CString::new(name.as_str());
if cstr.is_err() {
return false
}
let cstr = cstr.unwrap();
unsafe {
let lib = Self::new(cstr, flags);
if lib.is_none() {
return false
}
closure(lib.unwrap());
}
true
}
pub unsafe fn new(name_c: CString, flags: ::RtldValue) -> Option<Self> {
let handle = ::libc::dlopen(name_c.as_ptr(), flags.to_libc());
if handle.is_null() {
return None
}
Some(Self {
handle,
name: name_c.into_string().unwrap(), table: HashMap::new(),
})
}
}
impl ::std::ops::Drop for Library {
fn drop(&mut self) {
if !self.handle.is_null() {
unsafe {
::libc::dlclose(self.handle);
}
}
}
}