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
/*!
High-level and safe API for opening and getting symbols from dynamic link libraries.
It is based on wrapping private symbols with public functions to prevent direct access
and supports automatic loading of symbols into structures.

This API solves the problem with dangling symbols by wrapping raw symbols with public functions.
User of API does not have direct access to raw symbols and therefore symbols cannot be copied.
Symbols and library handle are kept in one `Container` structure and therefore both the the library
and symbols get released at the same time.

#Example

```no_run
#[macro_use]
extern crate dlopen_derive;
extern crate dlopen;
use dlopen::wrapper::{Container, WrapperApi};

#[derive(WrapperApi)]
struct Example<'a> {
    do_something: extern "C" fn(),
    add_one: unsafe extern "C" fn (arg: i32) -> i32,
    global_count: &'a mut u32,
}

fn main () {
let mut container: Container<Example> = unsafe { Container::load("libexample.dylib")}.unwrap();
container.do_something();
let _result = unsafe { container.add_one(5) };
*container.global_count_mut() += 1;

//symbols are released together with library handle
//this prevents dangling symbols
drop(container);
}
```

Unfortunately in Rust it is not possible to create an API for dynamic link libraries that would
be 100% safe. This API aims to be 99% safe by providing zero cost functional wrappers around
raw symbols. However it is possible to make a mistake if you create API as a standalone object
(not in container):

#Example of a mistake - dangling symbol

```no_run
#[macro_use]
extern crate dlopen_derive;
extern crate dlopen;
use dlopen::wrapper::{Container, WrapperApi};
use dlopen::raw::Library;

#[derive(WrapperApi)]
struct Example<'a> {
    do_something: extern "C" fn(),
    add_one: unsafe extern "C" fn (arg: i32) -> i32,
    global_count: &'a mut u32,
}

fn main () {
let lib = Library::open("libexample.dylib").unwrap();
let mut api = unsafe{Example::load(&lib)};
drop(lib);

//api has now dangling symbols

}
```

To prevent this mistake don't use structures implementing `WrapperApi` directly, but rather use
`Container` as in the first example.

**Note:** This API has a broad support for optional symbols (this solves the issue with multiple
versions of one dynamic link library that have different sets of symbols). Please refer to the
documentation of
[`OptionalContainer`](./struct.OptionalContainer.html)
and
[`WrapperMultiApi`](./trait.WrapperMultiApi.html).
*/

mod api;
mod multi_api;
mod container;
mod optional;
mod option;
pub use self::api::WrapperApi;
pub use self::multi_api::WrapperMultiApi;
pub use self::container::Container;
pub use self::optional::OptionalContainer;