#![cfg_attr(docsrs, feature(doc_cfg))]
mod sealed;
pub mod os;
#[cfg(unix)]
use os::unix as imp;
#[cfg(windows)]
use os::windows as imp;
pub mod img;
pub mod sync;
mod weak;
pub use weak::Weak;
mod sym;
pub use sym::Symbol;
use std::{
ffi,
io,
path,
};
#[cfg(feature = "dylink_macro")]
pub use dylink_macro::dylink;
#[doc = include_str!("../README.md")]
#[cfg(all(doctest, windows))]
struct ReadmeDoctests;
#[derive(Debug)]
#[cfg_attr(not(doc), repr(transparent))]
pub struct Library(imp::InnerLibrary);
unsafe impl Send for Library {}
unsafe impl Sync for Library {}
impl crate::sealed::Sealed for Library {}
impl Library {
#[doc(alias = "dlopen", alias = "LoadLibrary")]
#[inline]
pub fn open<P: AsRef<path::Path>>(path: P) -> io::Result<Self> {
unsafe { imp::InnerLibrary::open(path.as_ref().as_os_str()) }.map(Self)
}
#[must_use]
#[inline]
pub fn this() -> Self {
unsafe { imp::InnerLibrary::this() }
.map(Library)
.expect("failed to acquire library process handle")
}
#[inline]
pub fn leak(self) -> *mut ffi::c_void {
self.0.0.as_ptr()
}
#[doc(alias = "dlsym")]
#[inline]
pub fn symbol(&self, name: &str) -> io::Result<*const Symbol> {
unsafe { self.0.symbol(name) }
}
#[doc(alias = "dlsym")]
#[inline]
pub fn raw_symbol(&self, name: &std::ffi::CStr) -> *const Symbol {
unsafe { self.0.raw_symbol(name) }
}
#[inline]
pub fn try_clone(&self) -> io::Result<Library> {
unsafe { self.0.try_clone().map(Library) }
}
pub fn to_image(&self) -> io::Result<&img::Image> {
unsafe { self.0.to_ptr().as_ref() }.ok_or(io::Error::new(
io::ErrorKind::Unsupported,
"Header cannot be retrieved on this platform. Use `Symbol::header` instead.",
))
}
pub fn downgrade(this: &Self) -> io::Result<weak::Weak> {
let base_addr = this.to_image()?;
Ok(weak::Weak {
base_addr,
path_name: base_addr.path().ok(),
})
}
pub fn close(self) -> io::Result<()> {
self.0.close()
}
}
#[macro_export]
macro_rules! lib {
($($name:expr),+ $(,)?) => {
[$($name),+].into_iter()
.find_map(|elem| $crate::Library::open(elem).ok())
};
}