[][src]Trait dlopen::wrapper::WrapperApi

pub trait WrapperApi where
    Self: Sized
{ unsafe fn load(lib: &Library) -> Result<Self, Error>; }

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

unsafe fn load(lib: &Library) -> Result<Self, Error>

Load symbols from provided library.

Loading content...

Implementations on Foreign Types

impl<T> WrapperApi for Option<T> where
    T: WrapperApi
[src]

Loading content...

Implementors

Loading content...