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;
println!("after change: {}", unsafe { **api.rust_i32_ptr });
println!("c_int={}", *api.c_int);
println!(
"c struct first: {}, second:{}",
api.c_struct.first,
api.c_struct.second
);
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);
}