pub struct Library { /* private fields */ }Expand description
A loaded dynamic library.
The library is unloaded when this value is dropped (or explicitly with
close). Symbols borrowed from it cannot outlive it.
§Libraries that cannot be unloaded
Borrowing stops your code from using a library after it is unloaded,
but some libraries leave things behind that keep running their code:
threads they started, thread-local destructors, atexit handlers, or
callbacks registered elsewhere. Unloading those crashes later, far from
the cause (libclang on Windows is one). Keep such libraries loaded for
the life of the process with leak, a static, or
OpenOptions::no_delete.
Implementations§
Source§impl Library
impl Library
Sourcepub unsafe fn open(path: impl AsRef<OsStr>) -> Result<Self>
pub unsafe fn open(path: impl AsRef<OsStr>) -> Result<Self>
Loads the library at path, or searches for it by name using the
platform’s rules when path contains no directory separator.
On Unix this is dlopen(path, RTLD_NOW | RTLD_LOCAL); use
os::unix::OpenOptions for other flags.
On Windows this is LoadLibraryExW(path, NULL, 0), with the system’s
error dialogs suppressed.
§Safety
Loading a library runs its initialisers (and, on Windows, DllMain),
which may do anything. The caller must trust the library.
Examples found in repository?
28fn main() -> dlsym::Result<()> {
29 // SAFETY: the C math library's initialisers are trusted.
30 let libm = unsafe { Library::open(LIBM) }?;
31
32 // SAFETY: `cos` has this signature.
33 let cos = unsafe { libm.get::<unsafe extern "C" fn(f64) -> f64>(c"cos") }?;
34 // SAFETY: `cos` is defined for every `f64`.
35 println!("cos(0) = {}", unsafe { cos.call((0.0,)) });
36
37 // Variadic functions are called through `with`; the raw function
38 // pointer cannot escape the closure without `unsafe`.
39 #[cfg(not(windows))]
40 let libc = Library::this()?;
41 // SAFETY: msvcrt is a system library.
42 #[cfg(windows)]
43 let libc = unsafe { Library::open("msvcrt.dll") }?;
44 // SAFETY: `sprintf` has this signature.
45 let sprintf = unsafe {
46 libc.get::<unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int>(c"sprintf")
47 }?;
48 let mut buf = [0 as c_char; 64];
49 // SAFETY: the buffer is large enough and the format matches.
50 unsafe {
51 sprintf.with(|f| {
52 f(
53 buf.as_mut_ptr(),
54 c"%s has %d symbols".as_ptr(),
55 c"this example".as_ptr(),
56 2,
57 )
58 })
59 };
60 // SAFETY: `sprintf` NUL-terminated the buffer.
61 let text = unsafe { CStr::from_ptr(buf.as_ptr()) };
62 println!("{}", text.to_string_lossy());
63
64 // `cos` borrows `libm`: uncommenting this line makes the call below a
65 // compile error instead of a use-after-unload.
66 // drop(libm);
67 // SAFETY: as above.
68 println!("cos(pi) = {}", unsafe { cos.call((std::f64::consts::PI,)) });
69 Ok(())
70}Sourcepub unsafe fn open_first<I>(candidates: I) -> Result<Self>
pub unsafe fn open_first<I>(candidates: I) -> Result<Self>
Tries each candidate in turn with open, returning
the first library that loads, or the last error if none does.
Useful for libraries whose file name differs across platforms or versions:
// SAFETY: zlib has no unsound initialisers.
let zlib = unsafe { Library::open_first(["libz.so.1", "libz.1.dylib", "zlib1.dll"]) };§Safety
Same as open, for every candidate.
Sourcepub fn this() -> Result<Self>
pub fn this() -> Result<Self>
Returns a handle to the running program.
On Unix this is dlopen(NULL, ..), which looks symbols up in the main
program and every library loaded with global visibility (including
libc). On Windows it is the executable module, which only exposes
symbols the executable itself exports.
Examples found in repository?
27fn main() -> dlsym::Result<()> {
28 #[cfg(not(windows))]
29 let lib = Library::this()?;
30 // SAFETY: msvcrt is a system library.
31 #[cfg(windows)]
32 let lib = unsafe { Library::open("msvcrt.dll") }?;
33 // Resolves every symbol now; a missing non-optional one is an error.
34 let libc = LibC::load(lib)?;
35
36 println!("labs(-42) = {}", libc.labs(-42));
37 // SAFETY: valid C strings.
38 unsafe {
39 println!("strlen(\"dlsym\") = {}", libc.strlen(c"dlsym".as_ptr()));
40 println!("atoi(\"123\") = {}", libc.atoi(c"123".as_ptr()));
41 }
42
43 let mut buf = [0 as c_char; 32];
44 // SAFETY: the buffer is large enough and the format matches.
45 unsafe {
46 libc.sprintf()
47 .with(|f| f(buf.as_mut_ptr(), c"%05.1f".as_ptr(), 2.5f64))
48 };
49 // SAFETY: `sprintf` NUL-terminated the buffer.
50 println!("sprintf = {:?}", unsafe { CStr::from_ptr(buf.as_ptr()) });
51
52 // SAFETY: never called with a null pointer here; we only check presence.
53 match unsafe { libc.strlcpy(buf.as_mut_ptr(), c"x".as_ptr(), buf.len()) } {
54 Some(n) => println!("strlcpy is available ({n})"),
55 None => println!("strlcpy is not available in this C library"),
56 }
57 Ok(())
58}More examples
28fn main() -> dlsym::Result<()> {
29 // SAFETY: the C math library's initialisers are trusted.
30 let libm = unsafe { Library::open(LIBM) }?;
31
32 // SAFETY: `cos` has this signature.
33 let cos = unsafe { libm.get::<unsafe extern "C" fn(f64) -> f64>(c"cos") }?;
34 // SAFETY: `cos` is defined for every `f64`.
35 println!("cos(0) = {}", unsafe { cos.call((0.0,)) });
36
37 // Variadic functions are called through `with`; the raw function
38 // pointer cannot escape the closure without `unsafe`.
39 #[cfg(not(windows))]
40 let libc = Library::this()?;
41 // SAFETY: msvcrt is a system library.
42 #[cfg(windows)]
43 let libc = unsafe { Library::open("msvcrt.dll") }?;
44 // SAFETY: `sprintf` has this signature.
45 let sprintf = unsafe {
46 libc.get::<unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int>(c"sprintf")
47 }?;
48 let mut buf = [0 as c_char; 64];
49 // SAFETY: the buffer is large enough and the format matches.
50 unsafe {
51 sprintf.with(|f| {
52 f(
53 buf.as_mut_ptr(),
54 c"%s has %d symbols".as_ptr(),
55 c"this example".as_ptr(),
56 2,
57 )
58 })
59 };
60 // SAFETY: `sprintf` NUL-terminated the buffer.
61 let text = unsafe { CStr::from_ptr(buf.as_ptr()) };
62 println!("{}", text.to_string_lossy());
63
64 // `cos` borrows `libm`: uncommenting this line makes the call below a
65 // compile error instead of a use-after-unload.
66 // drop(libm);
67 // SAFETY: as above.
68 println!("cos(pi) = {}", unsafe { cos.call((std::f64::consts::PI,)) });
69 Ok(())
70}Sourcepub unsafe fn get<T: SymbolType>(
&self,
name: impl SymbolName,
) -> Result<Symbol<'_, T>>
pub unsafe fn get<T: SymbolType>( &self, name: impl SymbolName, ) -> Result<Symbol<'_, T>>
Looks up a symbol, borrowing the library for as long as the returned
Symbol is alive.
§Safety
T must match the symbol’s actual type: the right signature and
calling convention for functions, the right pointee for data. A
mismatch is undefined behaviour once the symbol is used.
Examples found in repository?
28fn main() -> dlsym::Result<()> {
29 // SAFETY: the C math library's initialisers are trusted.
30 let libm = unsafe { Library::open(LIBM) }?;
31
32 // SAFETY: `cos` has this signature.
33 let cos = unsafe { libm.get::<unsafe extern "C" fn(f64) -> f64>(c"cos") }?;
34 // SAFETY: `cos` is defined for every `f64`.
35 println!("cos(0) = {}", unsafe { cos.call((0.0,)) });
36
37 // Variadic functions are called through `with`; the raw function
38 // pointer cannot escape the closure without `unsafe`.
39 #[cfg(not(windows))]
40 let libc = Library::this()?;
41 // SAFETY: msvcrt is a system library.
42 #[cfg(windows)]
43 let libc = unsafe { Library::open("msvcrt.dll") }?;
44 // SAFETY: `sprintf` has this signature.
45 let sprintf = unsafe {
46 libc.get::<unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int>(c"sprintf")
47 }?;
48 let mut buf = [0 as c_char; 64];
49 // SAFETY: the buffer is large enough and the format matches.
50 unsafe {
51 sprintf.with(|f| {
52 f(
53 buf.as_mut_ptr(),
54 c"%s has %d symbols".as_ptr(),
55 c"this example".as_ptr(),
56 2,
57 )
58 })
59 };
60 // SAFETY: `sprintf` NUL-terminated the buffer.
61 let text = unsafe { CStr::from_ptr(buf.as_ptr()) };
62 println!("{}", text.to_string_lossy());
63
64 // `cos` borrows `libm`: uncommenting this line makes the call below a
65 // compile error instead of a use-after-unload.
66 // drop(libm);
67 // SAFETY: as above.
68 println!("cos(pi) = {}", unsafe { cos.call((std::f64::consts::PI,)) });
69 Ok(())
70}Sourcepub unsafe fn get_arc<T: SymbolType>(
self: &Arc<Self>,
name: impl SymbolName,
) -> Result<ArcSymbol<T>>
pub unsafe fn get_arc<T: SymbolType>( self: &Arc<Self>, name: impl SymbolName, ) -> Result<ArcSymbol<T>>
Sourcepub fn path(&self) -> Option<PathBuf>
pub fn path(&self) -> Option<PathBuf>
Returns the path the library was loaded from, if the platform can
tell (glibc, Apple platforms and Windows). For Library::this, this
is the executable.