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) } }