Trait dlopen::wrapper::WrapperApi [−][src]
Trait for defining library API.
This trait is intended to be used with #[derive(WrapperApi)]
macro defined in the
dlopen_derive
crate. It forces several restrictions on types that implement it:
- Only structures can implement this trait.
- All fields need to be private.
- Only functions, references and pointers are allowed.
- You can’t define a type using
type Fun =fn();
and use it in the structure. This is a limitation of the Rust reflection mechanism. Only raw functions, references and pointers are allowed. - All arguments of functions need to be named.
The derive
macro not only generates implementation of load()
function, but it also generates
safe wrappers around the loaded symbols. These wrappers are named exactly like the field that
they wrap. Wrappers of functions have the same arguments like original functions and wrappers of
references are just simple accessors in the form of <field_name>(&self) -> &FieldType
or
<field_name>_mut(&mut self) -> &mut FieldType
.
Wrappers are not generated only for:
- Pointers - there is no safe way of preventing dangling symbols if a user has a direct access to
pointers. The recommended approach here is to either use references instead of pointers or
to manually create safe wrappers. For example C
const char *
can be manually converted into& std::ffi::CStr
. - Variadic functions. Rust doesn’t have any mechanism that allows creating safe wrappers around them. You need to handle them manually.
#Example
#[macro_use] extern crate dlopen_derive; extern crate dlopen; extern crate libc; use dlopen::wrapper::{WrapperApi, Container}; use libc::{c_char}; use std::ffi::CStr; #[derive(WrapperApi)] struct Example<'a> { #[dlopen_name="function"] do_something: extern "C" fn(), add_one: unsafe extern "C" fn (arg: i32) -> i32, global_count: &'a mut u32, c_string: * const c_char, #[dlopen_allow_null] maybe_null_ptr: * const (), } //wrapper for c_string won't be generated, implement it here impl<'a> Example<'a> { pub fn c_string(&self) -> &CStr { unsafe {CStr::from_ptr(self.c_string)} } } fn main () { let mut cont: Container<Example> = unsafe { Container::load("libexample.dylib")}.unwrap(); cont.do_something(); let _result = unsafe { cont.add_one(5) }; *cont.global_count_mut() += 1; println!("C string: {}", cont.c_string().to_str().unwrap()) }
Note: WrapperApi
should only be used together with Container
structure, never to create
a standalone object. API and library handle need to be kept together to prevent dangling symbols.
Note: By default obtained symbol name is the field name. You can change this by assigning the “dlopen_name” attribute to the given field.
Note: By default Error::NullSymbol
is returned if the loaded symbol name has a null value.
While null is a valid value of a exported symbol, it is usually not expected by users of libraries.
If in your scenario null is an acceptable value, you should assign
“dlopen_allow_null” attribute to the given field. Of course this makes sense only if the field
is of pointer type.
Required methods
Loading content...Implementations on Foreign Types
impl<T> WrapperApi for Option<T> where
T: WrapperApi,
[src]
Loading content...T: WrapperApi,