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
use DataUnsafe;
use error::*;
use FuncUnsafe;
use os::uses::Lib as InnerLib;
use std::mem;
use std::path::Path;
use util;

/// A shared library which does not track its [Symbols](trait.Symbol.html).
/// The inner library may be dropped at any time, even if it has loose symbols.
#[derive(Debug)]
pub struct LibUnsafe {
    inner: InnerLib,
}

impl LibUnsafe {
    /// Opens a shared library at the specified path.
    /// The path is used in conjunction with platform specific shared library search paths to determine which shared library will be opened. Search paths vary across environments and are not discussed in this documentation. The behavior of this function when it is called on the same path multiple times is platform specific. If you wish to obtain multiple copies of a library within the same code base in a platform generic way, you should load the symbol once in a [LibTracked](struct.LibTracked.html) like [LibArc](struct.LibArc.html), or [LibRc](struct.LibRc.html), and pass around copies of the [LibTracked](struct.LibTracked.html).
    ///
    /// # Errors
    /// A `LibraryOpen` error will be returned as a [SharedlibError](enum.SharedlibError.html) variant if there is a problem opening the shared library. For instance, this may happen if the shared library is not at the path specified.
    ///
    /// # Safety
    /// Opening a shared library may execute code within the shared library. Since it is impossible to guarantee that the code witin the shared library is safe, the call to new is unsafe.
    ///
    /// # Examples
    /// ``` no_run
    /// # use sharedlib::error::*;
    /// # use sharedlib::LibUnsafe;
    /// # fn test() -> Result<()> {
    /// let lib = try!(unsafe { LibUnsafe::new("examplelib.dll") });
    /// # Ok(())
    /// # }
    /// ```
    pub unsafe fn new<TPath>(path_to_lib: TPath) -> Result<Self>
        where TPath: AsRef<Path> {
        let inner = try!(InnerLib::new(path_to_lib));
        let result =
            LibUnsafe {
                inner: inner,
            };
        Ok(result)
    }

    /// Finds and returns a data symbol within the shared library.
    /// By passing in a null terminated string, an extra allocation may be avoided.
    ///
    /// # Errors
    /// A `LibraryFindSymbol` error will be returned as a [SharedlibError](enum.SharedlibError.html) variant if there is a problem finding the symbol. For instance, this may happen if the shared library does not contain the requested symbol.
    ///
    /// # Safety
    /// This function is not type safe so there is no guarntee that `T` is really the type of the symbol. Using a symbol as a `T` when the symbol is not really of type `T` causes undefined behavior.
    ///
    /// # Examples
    /// Finding data convieniently:
    ///
    /// ``` no_run
    /// # use sharedlib::DataUnsafe;
    /// # use sharedlib::error::*;
    /// # use sharedlib::LibUnsafe;
    /// # use sharedlib::Symbol;
    /// # fn test() -> Result<()> {
    /// # let lib = try!(unsafe { LibUnsafe::new("examplelib.dll") });
    /// let some_usize: DataUnsafe<usize> = try!(unsafe { lib.find_data("some_usize") });
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// Finding data with maximum performance:
    ///
    /// ``` no_run
    /// # use sharedlib::DataUnsafe;
    /// # use sharedlib::error::*;
    /// # use sharedlib::LibUnsafe;
    /// # use sharedlib::Symbol;
    /// # fn test() -> Result<()> {
    /// # let lib = try!(unsafe { LibUnsafe::new("examplelib.dll") });
    /// let some_usize: DataUnsafe<usize> = try!(unsafe { lib.find_data("some_usize\0") });
    /// # Ok(())
    /// # }
    /// ```
    pub unsafe fn find_data<T, TStr>(&self, symbol: TStr) -> Result<DataUnsafe<T>>
        where TStr: AsRef<str> {
        match util::null_terminate(&symbol) {
            Some(symbol) => self.inner.find(symbol),
            None => self.inner.find(symbol),
        }
    }

    /// Finds and returns a function symbol within the shared library.
    /// By passing in a null terminated string, an extra allocation may be avoided.
    ///
    /// # Errors
    /// A `LibraryFindSymbol` error will be returned as a [SharedlibError](enum.SharedlibError.html) variant if there is a problem finding the symbol. For instance, this may happen if the shared library does not contain the requested symbol.
    ///
    /// # Safety
    /// This function is not type safe so there is no guarntee that `T` is really the type of the symbol. Using a symbol as a `T` when the symbol is not really of type `T` causes undefined behavior.
    ///
    /// # Examples
    /// Finding a function convieniently:
    ///
    /// ``` no_run
    /// # use sharedlib::error::*;
    /// # use sharedlib::FuncUnsafe;
    /// # use sharedlib::LibUnsafe;
    /// # use sharedlib::Symbol;
    /// # fn test() -> Result<()> {
    /// # let lib = try!(unsafe { LibUnsafe::new("examplelib.dll") });
    /// let some_func: FuncUnsafe<fn()> = try!(unsafe { lib.find_func("some_func") });
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// Finding a function with maximum performance:
    ///
    /// ``` no_run
    /// # use sharedlib::error::*;
    /// # use sharedlib::FuncUnsafe;
    /// # use sharedlib::LibUnsafe;
    /// # use sharedlib::Symbol;
    /// # fn test() -> Result<()> {
    /// # let lib = try!(unsafe { LibUnsafe::new("examplelib.dll") });
    /// let some_func: FuncUnsafe<fn()> = try!(unsafe { lib.find_func("some_func\0") });
    /// # Ok(())
    /// # }
    /// ```
    pub unsafe fn find_func<T, TStr>(&self, symbol: TStr) -> Result<FuncUnsafe<T>>
        where T: Copy,
              TStr: AsRef<str> {
        let func =
            match util::null_terminate(&symbol) {
                Some(symbol) => try!(self.inner.find::<u8, _>(symbol)),
                None => try!(self.inner.find::<u8, _>(symbol)),
            };
        let func_ref = &func;
        let result: T = mem::transmute_copy(func_ref);
        Ok(result)
    }
}