Skip to main content

Library

Struct Library 

Source
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

Source

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?
examples/symbols.rs (line 30)
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}
Source

pub unsafe fn open_first<I>(candidates: I) -> Result<Self>
where I: IntoIterator, I::Item: AsRef<OsStr>,

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.

Source

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?
examples/bindings.rs (line 29)
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
Hide additional examples
examples/symbols.rs (line 40)
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}
Source

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?
examples/symbols.rs (line 33)
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}
Source

pub unsafe fn get_arc<T: SymbolType>( self: &Arc<Self>, name: impl SymbolName, ) -> Result<ArcSymbol<T>>

Looks up a symbol, keeping the library alive through the Arc rather than a borrow. Useful for storing symbols in 'static contexts.

§Safety

Same as get.

Source

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.

Source

pub fn leak(self) -> &'static Library

Keeps the library loaded for the rest of the program, so symbols borrowed from it are 'static.

Source

pub fn close(self) -> Result<()>

Unloads the library, reporting any error from the loader. Dropping a Library does the same but ignores errors.

Trait Implementations§

Source§

impl Debug for Library

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for Library

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl LibraryExt for Library

Source§

unsafe fn get_versioned<T: SymbolType>( &self, name: impl SymbolName, version: impl SymbolName, ) -> Result<Symbol<'_, T>>

Looks up a specific version of a symbol (dlvsym), such as ("memcpy", "GLIBC_2.2.5"). Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.