use super::super::err::Error;
use std::ffi::{CStr, CString, OsStr};
#[cfg(unix)]
use super::unix::{
addr_info_cleanup, addr_info_init, addr_info_obtain, close_lib, get_sym, open_lib, open_self,
};
#[cfg(windows)]
use super::windows::{
addr_info_cleanup, addr_info_init, addr_info_obtain, close_lib, get_sym, open_lib, open_self,
};
#[cfg(unix)]
pub use super::unix::Handle;
#[cfg(windows)]
pub use super::windows::Handle;
use std::mem::{size_of, transmute_copy};
#[derive(Debug)]
pub struct Library {
handle: Handle,
}
impl Library {
pub fn open<S>(name: S) -> Result<Library, Error>
where
S: AsRef<OsStr>,
{
Ok(Self {
handle: unsafe { open_lib(name.as_ref(), None) }?,
})
}
pub fn open_with_flags<S>(name: S, flags: Option<i32>) -> Result<Library, Error>
where
S: AsRef<OsStr>,
{
Ok(Self {
handle: unsafe { open_lib(name.as_ref(), flags) }?,
})
}
pub fn open_self() -> Result<Library, Error> {
Ok(Self {
handle: unsafe { open_self() }?,
})
}
pub unsafe fn symbol<T>(&self, name: &str) -> Result<T, Error> {
unsafe {
let cname = CString::new(name)?;
self.symbol_cstr(cname.as_ref())
}
}
pub unsafe fn symbol_cstr<T>(&self, name: &CStr) -> Result<T, Error> {
unsafe {
if size_of::<T>() != size_of::<*mut ()>() {
panic!(
"The type passed to dlopen2::Library::symbol() function has a different size than a \
pointer - cannot transmute"
);
}
let raw = get_sym(self.handle, name)?;
if raw.is_null() {
Err(Error::NullSymbol)
} else {
Ok(transmute_copy(&raw))
}
}
}
pub unsafe fn into_raw(&self) -> Handle {
self.handle
}
}
impl Drop for Library {
fn drop(&mut self) {
self.handle = close_lib(self.handle);
}
}
unsafe impl Sync for Library {}
unsafe impl Send for Library {}
#[derive(Debug)]
pub struct OverlappingSymbol {
pub name: String,
pub addr: *const (),
}
#[derive(Debug)]
pub struct AddressInfo {
pub dll_path: String,
pub dll_base_addr: *const (),
pub overlapping_symbol: Option<OverlappingSymbol>,
}
pub struct AddressInfoObtainer {}
impl Default for AddressInfoObtainer {
fn default() -> Self {
Self::new()
}
}
impl AddressInfoObtainer {
pub fn new() -> AddressInfoObtainer {
unsafe { addr_info_init() };
AddressInfoObtainer {}
}
pub unsafe fn obtain(&self, addr: *const ()) -> Result<AddressInfo, Error> {
unsafe { addr_info_obtain(addr) }
}
}
impl Drop for AddressInfoObtainer {
fn drop(&mut self) {
unsafe { addr_info_cleanup() }
}
}