1 // dlsym.rs is taken from mio
2 // https://github.com/carllerche/mio/blob/master/src/sys/unix/dlsym.rs
3
4 use std::marker;
5 use std::mem;
6 use std::sync::atomic::{AtomicUsize, Ordering};
7
8 use libc;
9
10 macro_rules! dlsym {
11 (fn $name:ident($($t:ty),*) -> $ret:ty) => (
12 #[allow(bad_style)]
13 static $name: $crate::dlsym::DlSym<unsafe extern fn($($t),*) -> $ret> =
14 $crate::dlsym::DlSym {
15 name: concat!(stringify!($name), "\0"),
16 addr: ::std::sync::atomic::AtomicUsize::new(0),
17 _marker: ::std::marker::PhantomData,
18 };
19 )
20 }
21
22 pub struct DlSym<F> {
23 pub name: &'static str,
24 pub addr: AtomicUsize,
25 pub _marker: marker::PhantomData<F>,
26 }
27
28 impl<F> DlSym<F> {
get(&self) -> Option<&F>29 pub fn get(&self) -> Option<&F> {
30 assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
31 unsafe {
32 if self.addr.load(Ordering::SeqCst) == 0 {
33 self.addr.store(fetch(self.name), Ordering::SeqCst);
34 }
35 if self.addr.load(Ordering::SeqCst) == 1 {
36 None
37 } else {
38 mem::transmute::<&AtomicUsize, Option<&F>>(&self.addr)
39 }
40 }
41 }
42 }
43
fetch(name: &str) -> usize44 unsafe fn fetch(name: &str) -> usize {
45 assert_eq!(name.as_bytes()[name.len() - 1], 0);
46 match libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize {
47 0 => 1,
48 n => n,
49 }
50 }
51