Module dlopen::wrapper [−][src]
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
#[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
#[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
and
WrapperMultiApi
.
Structs
Container | Container for both a dynamic load library handle and its API. |
OptionalContainer | Container for a library handle and both obligatory and optional APIs inside one structure. |
Traits
WrapperApi | Trait for defining library API. |
WrapperMultiApi | Allows creation of complex, optional APIs. |