Search code examples
rustdynamicdllruntimedylib

How do I call a function with parameters from dll in rust


I am using libloading to loading dll, it requires me to confirm the parameter what function need, like this:

let lib = libloading::Library::new("libstd.dylib").unwrap();
let func: Symbol<fn(&str)> = lib.get(b"println").unwrap();
//               ^ it requires to confirm the parameter what function need
func("Hello World");

But I want to make a function to call functions from libstd.dylib, Both parameters and types are indeterminate

fn call_from_libstd() {} // I don't know how to implement this function 

call_from_libstd("println", "Hello World");
let c = call_from_libstd("add", 10, 20);
println("{}", c);

The functions form dll is like

#[no_mangle]
pub fn println(str: &str) {
    println!("{}", str);
}

#[no_mangle]
pub fn add (a: usize,b:usize) -> usize {
    return a + b;
}

Solution

  • I solved this problem by macros, and i published my code to crates this is the link.

    the main code if:

    macro_rules! get_libfn {
        ($lib_path: expr, $fn_name: expr, $call_name: ident, $ret: ty, $($v: ident: $t:ty),*) => {
            pub fn $call_name($($v: $t),*) -> $ret {
                unsafe {
                    let lib = libloading::Library::new($lib_path).unwrap();
                    let func: libloading::Symbol<fn($($t,)*) -> $ret> = lib.get($fn_name.as_bytes()).unwrap();
                    func($($v,)*)
                }
            }
        };
        ($lib_path: expr, $fn_name: expr, $call_name:ident, $ret: ty) => {
            pub fn $call_name() -> $ret {
                unsafe {
                    let lib = libloading::Library::new($lib_path).unwrap();
                    let func: libloading::Symbol<fn() -> $ret> = lib.get($fn_name.as_bytes()).unwrap();
                    func()
                }
            }
        };
    }
    
    get_libfn!("libstd.dylib", "println", my_println, (), str: &str);
    my_println("Hello World");