1 | //! Library loading routines. |
2 | |
3 | use std::ops::{Deref, DerefMut}; |
4 | use std::sync::Arc; |
5 | |
6 | use libloading::Library; |
7 | |
8 | #[cfg (windows)] |
9 | use libloading::os::windows::{Library as WinLibrary, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS}; |
10 | |
11 | pub trait SymLoading { |
12 | /// # Safety |
13 | /// The library must be unsured to live long enough. |
14 | unsafe fn load_with(lib: &Library) -> Self; |
15 | } |
16 | |
17 | #[derive (Clone)] |
18 | pub struct SymWrapper<T> { |
19 | sym: T, |
20 | _lib: Arc<Library>, |
21 | } |
22 | |
23 | impl<T: SymLoading> SymWrapper<T> { |
24 | pub unsafe fn new(lib_paths: &[&str]) -> Result<Self, ()> { |
25 | unsafe { |
26 | for path: &&str in lib_paths { |
27 | #[cfg (windows)] |
28 | let lib = WinLibrary::load_with_flags(path, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) |
29 | .map(From::from); |
30 | |
31 | #[cfg (not(windows))] |
32 | let lib: Result = Library::new(filename:path); |
33 | |
34 | if let Ok(lib: Library) = lib { |
35 | return Ok(SymWrapper { sym: T::load_with(&lib), _lib: Arc::new(data:lib) }); |
36 | } |
37 | } |
38 | } |
39 | |
40 | Err(()) |
41 | } |
42 | } |
43 | |
44 | impl<T> Deref for SymWrapper<T> { |
45 | type Target = T; |
46 | |
47 | fn deref(&self) -> &Self::Target { |
48 | &self.sym |
49 | } |
50 | } |
51 | |
52 | impl<T> DerefMut for SymWrapper<T> { |
53 | fn deref_mut(&mut self) -> &mut Self::Target { |
54 | &mut self.sym |
55 | } |
56 | } |
57 | |