dlopen 0.1.8

Library for opening and operating on dynamic link libraries (also known as shared objects or shared libraries). This is a modern and more flexible alternative to the already existing libraries like libloading or sharedlib
Documentation
extern crate dlopen;
#[macro_use]
extern crate dlopen_derive;
extern crate libc;

mod commons;
use commons::{example_lib_path, SomeData};
use dlopen::symbor::{Library, PtrOrNull, Ref, RefMut, SymBorApi, Symbol};
use libc::{c_char, c_int};
use std::ffi::CStr;


#[derive(SymBorApi)]
struct Api<'a> {
    pub rust_fun_print_something: Symbol<'a, fn()>,
    pub rust_fun_add_one: Symbol<'a, fn(i32) -> i32>,
    pub c_fun_print_something_else: Symbol<'a, unsafe extern "C" fn()>,
    pub c_fun_add_two: Symbol<'a, unsafe extern "C" fn(c_int) -> c_int>,
    pub rust_i32: Ref<'a, i32>,
    pub rust_i32_mut: RefMut<'a, i32>,
    #[dlopen_name = "rust_i32_mut"] pub rust_i32_ptr: Symbol<'a, *const i32>,
    pub c_int: Ref<'a, c_int>,
    pub c_struct: Ref<'a, SomeData>,
    pub rust_str: Ref<'a, &'static str>,
    pub c_const_char_ptr: PtrOrNull<'a, c_char>,
}

fn main() {
    let lib_path = example_lib_path();
    let lib = Library::open(lib_path).expect("Could not open library");
    let mut api = unsafe { Api::load(&lib) }.expect("Could not load the API");

    (api.rust_fun_print_something)();

    println!(" 5+1={}", (api.rust_fun_add_one)(5));

    unsafe { (api.c_fun_print_something_else)() };

    println!("2+2={}", unsafe { (api.c_fun_add_two)(2) });

    println!("const rust i32 value: {}", *api.rust_i32);

    println!("mutable rust i32 value: {}", *api.rust_i32_mut);

    *api.rust_i32_mut = 55;

    //for a change use pointer to obtain its value
    println!("after change: {}", unsafe { **api.rust_i32_ptr });

    //the same with C
    println!("c_int={}", *api.c_int);

    //now static c struct
    println!(
        "c struct first: {}, second:{}",
        api.c_struct.first,
        api.c_struct.second
    );

    //let's play with strings
    println!("Rust says: {}", *api.rust_str);

    let converted = unsafe { CStr::from_ptr(*api.c_const_char_ptr) }
        .to_str()
        .unwrap();
    println!("And now C says: {}", converted);
}