dlopen/wrapper/container.rs
1use super::super::raw::Library;
2use super::super::Error;
3use std::ops::{Deref, DerefMut};
4use super::api::WrapperApi;
5use std::ffi::OsStr;
6
7/**
8Container for both a dynamic load library handle and its API.
9
10Keeping both library and its symbols together makes it safe to use it because symbols are released
11together with the library. `Container` also doesn't have any external lifetimes - this makes it
12easy to use `Container` inside structures.
13
14#Example
15
16```no_run
17#[macro_use]
18extern crate dlopen_derive;
19extern crate dlopen;
20extern crate libc;
21use dlopen::wrapper::{Container, WrapperApi};
22use libc::{c_char};
23use std::ffi::CStr;
24
25#[derive(WrapperApi)]
26struct Example<'a> {
27 do_something: extern "C" fn(),
28 add_one: unsafe extern "C" fn (arg: i32) -> i32,
29 global_count: &'a mut u32,
30 c_string: * const c_char
31}
32
33//wrapper for c_string won't be generated, implement it here
34impl<'a> Example<'a> {
35 pub fn c_string(&self) -> &CStr {
36 unsafe {CStr::from_ptr(self.c_string)}
37 }
38}
39
40fn main () {
41 let mut container: Container<Example> = unsafe { Container::load("libexample.dylib")}.unwrap();
42 container.do_something();
43 let _result = unsafe { container.add_one(5) };
44 *container.global_count_mut() += 1;
45 println!("C string: {}", container.c_string().to_str().unwrap())
46}
47```
48*/
49pub struct Container<T>
50where
51 T: WrapperApi,
52{
53 #[allow(dead_code)]
54 //this is not dead code because destructor of Library deallocates the library
55 lib: Library,
56 api: T,
57}
58
59impl<T> Container<T>
60where
61 T: WrapperApi,
62{
63 ///Open the library using provided file name or path and load all symbols.
64 pub unsafe fn load<S>(name: S) -> Result<Container<T>, Error>
65 where
66 S: AsRef<OsStr>,
67 {
68 let lib = Library::open(name)?;
69 let api = T::load(&lib)?;
70 Ok(Self { lib: lib, api: api })
71 }
72 ///Load all symbols from the program itself.
73 ///
74 /// This allows a shared library to load symbols of the program it was
75 /// loaded into.
76 pub unsafe fn load_self() -> Result<Container<T>, Error> {
77 let lib = Library::open_self()?;
78 let api = T::load(&lib)?;
79 Ok(Self { lib: lib, api: api })
80 }
81}
82
83impl<T> Deref for Container<T>
84where
85 T: WrapperApi,
86{
87 type Target = T;
88 fn deref(&self) -> &T {
89 &self.api
90 }
91}
92
93impl<T> DerefMut for Container<T>
94where
95 T: WrapperApi,
96{
97 fn deref_mut(&mut self) -> &mut T {
98 &mut self.api
99 }
100}