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
use ::libc::c_void;
use ::std::collections::HashMap;
use ::std::ffi::CString;
pub struct Library {
pub(crate) handle: *mut c_void,
pub(crate) name: String,
pub(crate) table: HashMap<String, *mut c_void>,
}
impl Library {
pub unsafe fn handle(&self) -> &*mut c_void {
&self.handle
}
pub unsafe fn table(&self) -> &HashMap<String, *mut c_void> {
&self.table
}
pub fn name(&self) -> String {
self.name.clone()
}
pub fn sym<T>(&mut self, name: String) -> Option<Box<T>> {
if self.table.contains_key(&name) {
let gotten = self.table.get(&name);
unsafe {
let gotten = Box::from_raw(*gotten.unwrap() as *mut T);
return Some(gotten)
}
}
if self.handle.is_null() {
return None
}
let name_c = CString::new(name.as_str());
if name_c.is_err() {
return None
}
let name_c = name_c.unwrap();
let sym: Box<T>;
unsafe {
let sym_c: *mut ::libc::c_void;
if name.is_empty() {
let name_c: *const ::libc::c_char = ::std::ptr::null();
sym_c = ::libc::dlsym(self.handle, name_c);
} else {
sym_c = ::libc::dlsym(self.handle, name_c.as_ptr());
}
sym = Box::from_raw(sym_c as *mut T);
self.table.insert(name, sym_c);
}
Some(sym)
}
pub fn open(name: String, flags: ::RtldValue, closure: fn(lib: Library)) -> bool {
let cstr = CString::new(name.as_str());
if cstr.is_err() {
return false
}
let cstr = cstr.unwrap();
unsafe {
let lib = Self::new(cstr, flags);
if lib.is_none() {
return false
}
closure(lib.unwrap());
}
true
}
pub unsafe fn new(name_c: CString, flags: ::RtldValue) -> Option<Self> {
let handle = ::libc::dlopen(name_c.as_ptr(), flags.to_libc());
if handle.is_null() {
return None
}
Some(Self {
handle,
name: name_c.into_string().unwrap(),
table: HashMap::new(),
})
}
}
impl ::std::ops::Drop for Library {
fn drop(&mut self) {
if !self.handle.is_null() {
unsafe {
::libc::dlclose(self.handle);
}
}
}
}