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
use super::api::SymBorApi; use super::Library; use std::mem::transmute; use std::ops::{Deref, DerefMut}; use std::ffi::OsStr; use super::super::Error; /** Container for both dynamic link library handle and its API. This structure solves an important issue: object oriented programming where the given structure has two objects and one of the objects has a reference to the second one. Normally you can't put `Library` and a structure that implements `SymBorApi` into one structure. This structure allows you to do it. #Example ```no_run #[macro_use] extern crate dlopen_derive; extern crate dlopen; use dlopen::symbor::{Library, Symbol, Ref, PtrOrNull, SymBorApi, Container}; #[derive(SymBorApi)] struct ExampleApi<'a> { pub fun: Symbol<'a, unsafe extern "C" fn(i32) -> i32>, pub glob_i32: Ref<'a, i32>, pub maybe_c_str: PtrOrNull<'a, u8>, } fn main(){ let cont: Container<ExampleApi> = unsafe{Container::load("libexample.so")} .expect("Could not load library or symbols"); println!("fun(4)={}", unsafe{(cont.fun)(4)}); println!("glob_i32={}", *cont.glob_i32); println!("The pointer is null={}", cont.maybe_c_str.is_null()); } ``` */ pub struct Container<T> where T: SymBorApi<'static>, { #[allow(dead_code)] lib: Library, api: T, } impl<T> Container<T> where T: SymBorApi<'static>, { ///Open dynamic link library and load symbols. pub unsafe fn load<S>(name: S) -> Result<Self, Error> where S: AsRef<OsStr>, { let lib = Library::open(name)?; //this is cheating of course //but it is safe because Library and api is placed in the same structure //and therefore it is released at the same time. let static_ref: &'static Library = transmute(&lib); let api = T::load(static_ref)?; Ok(Self { api: api, lib: lib }) } ///Load all symbols from the program itself. /// /// This allows a shared library to load symbols of the program it was /// loaded into. pub unsafe fn load_self() -> Result<Self, Error> { let lib = Library::open_self()?; //this is cheating of course //but it is safe because Library and api is placed in the same structure //and therefore it is released at the same time. let static_ref: &'static Library = transmute(&lib); let api = T::load(static_ref)?; Ok(Self { api: api, lib: lib }) } } impl<T> Deref for Container<T> where T: SymBorApi<'static>, { type Target = T; fn deref(&self) -> &T { &self.api } } impl<T> DerefMut for Container<T> where T: SymBorApi<'static>, { fn deref_mut(&mut self) -> &mut T { &mut self.api } }