Files
ansi_term
arraydeque
atty
bear_lib_terminal
bear_lib_terminal_sys
bitflags
cfg_if
clap
const_cstr
dirs
dirs_sys
dlopen
dlopen_derive
downcast_rs
lazy_static
libc
num_traits
pir_8_as
pir_8_disasm
pir_8_emu
proc_macro2
quote
serde
serde_derive
strsim
syn
textwrap
time
tinyfiledialogs
toml
unicode_width
unicode_xid
vec_map
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use std::ffi::CStr;
use super::symbol::Symbol;
use super::ptr_or_null::PtrOrNull;
use super::ptr_or_null_mut::PtrOrNullMut;
use super::super::raw::Library as RawLib;
use std::ffi::{CString, OsStr};
use std::ptr::{null, null_mut};

use super::super::err::Error;

/**
Safe wrapper around dynamic link library handle.

Methods of `Library` return only types that make the library borrowed. Therefore the problem with
dangling symbols is prevented.

**Note:**: It is recommended that you use certain methods in certain situations:

* `symbol()` - for obtaining functions and pointers (but only if you can't use references
    instead of pointers and you do not accept null value of a pointer).
* `reference()` and `reference_mut()` - for obtaining access to
    statically allocated objects - either constant or mutable.
* `ptr_or_null()` and `ptr_or_null_mut()` - for obtaining pointers if you accept null values of
pointers (in 99% of cases you should rather use previously mentioned methods).

#Example

```no_run
extern crate dlopen;
use dlopen::symbor::Library;

fn main(){
    let lib = Library::open("libexample.dylib").unwrap();
    let fun = unsafe{lib.symbol::<unsafe extern "C" fn()>("function")}.unwrap();
    unsafe{fun()};
    let glob_val: &mut u32 = unsafe{lib.reference_mut("glob_val")}.unwrap();
    *glob_val = 42;
    let ptr_or_null = unsafe{lib.ptr_or_null::<()>("void_ptr")}.unwrap();
    println!("Pointer is null: {}", ptr_or_null.is_null());
}
```
*/
pub struct Library {
    lib: RawLib,
}

impl Library {
    ///Open dynamic link library using provided file name or path.
    pub fn open<S>(name: S) -> Result<Library, Error>
    where
        S: AsRef<OsStr>,
    {
        Ok(Library {
            lib: RawLib::open(name)?,
        })
    }

    /// Open the program itself as library.
    ///
    /// This allows a shared library to load symbols of the program it was
    /// loaded into.
    pub fn open_self() -> Result<Library, Error> {
        Ok(Library {
            lib: RawLib::open_self()?,
        })
    }

    /// Obtain a symbol from library.
    ///
    /// This method is the most general one and allows obtaining basically everything assuming
    /// that the value of the given symbol cannot be null (use `ptr_or_null()` for this case).
    /// However the `reference()` and `reference_mut()` methods return a native reference and they
    /// are more programmer friendly when you try accessing statically allocated data in
    /// the library.
    pub unsafe fn symbol<T>(&self, name: &str) -> Result<Symbol<T>, Error> {
        Ok(Symbol::new(self.lib.symbol(name)?))
    }

    ///Equivalent of the `symbol()` method but takes `CStr` as a argument.
    pub unsafe fn symbol_cstr<T>(&self, name: &CStr) -> Result<Symbol<T>, Error> {
        Ok(Symbol::new(self.lib.symbol_cstr(name)?))
    }

    ///Obtain a const pointer from library.
    ///
    /// **Note:** This method is only recommended for data
    /// that can't be accessed as a reference and that can have a null pointer value
    /// (so not in 99% of cases).
    pub unsafe fn ptr_or_null<T>(&self, name: &str) -> Result<PtrOrNull<T>, Error> {
        let cname = CString::new(name)?;
        self.ptr_or_null_cstr(cname.as_ref())
    }

    ///Equivalent of the `pointer()` method but takes `CStr` as a argument.
    pub unsafe fn ptr_or_null_cstr<T>(&self, name: &CStr) -> Result<PtrOrNull<T>, Error> {
        let raw_ptr = match self.lib.symbol_cstr(name) {
            Ok(val) => val,
            Err(err) => match err {
                Error::NullSymbol => null(),
                _ => return Err(err),
            },
        };
        Ok(PtrOrNull::new(raw_ptr))
    }

    ///Obtain a mutable pointer from library.
    ///
    /// **Note:** This method is only recommended for data
    /// that can't be accessed as a reference and that can have a null pointer value
    /// (so not in 99% of cases).
    pub unsafe fn ptr_or_null_mut<T>(&self, name: &str) -> Result<PtrOrNullMut<T>, Error> {
        let cname = CString::new(name)?;
        self.ptr_or_null_mut_cstr(cname.as_ref())
    }

    ///Equivalent of the `pointer_mut()` method but takes `CStr` as a argument.
    pub unsafe fn ptr_or_null_mut_cstr<T>(&self, name: &CStr) -> Result<PtrOrNullMut<T>, Error> {
        let raw_ptr = match self.lib.symbol_cstr(name) {
            Ok(val) => val,
            Err(err) => match err {
                Error::NullSymbol => null_mut(),
                _ => return Err(err),
            },
        };
        Ok(PtrOrNullMut::new(raw_ptr))
    }

    ///Obtain const reference to statically allocated data in the library.
    pub unsafe fn reference<T>(&self, name: &str) -> Result<&T, Error> {
        self.lib.symbol(name)
    }

    ///Equivalent of the `reference()` method but takes `CStr` as a argument.
    pub unsafe fn reference_cstr<T>(&self, name: &CStr) -> Result<&T, Error> {
        self.lib.symbol_cstr(name)
    }

    ///Obtain mutable reference to statically allocated data in the library.
    pub unsafe fn reference_mut<T>(&self, name: &str) -> Result<&mut T, Error> {
        self.lib.symbol(name)
    }

    ///Equivalent of the `reference_mut()` method but takes `CStr` as a argument.
    pub unsafe fn reference_mut_cstr<T>(&self, name: &CStr) -> Result<&mut T, Error> {
        self.lib.symbol_cstr(name)
    }
}

unsafe impl Send for Library {}
unsafe impl Sync for Library {}