如何动态调用共享库中的函数?

How to dynamically call a function in a shared library?

我有一个 Rust 项目,设置为可执行文件。我正在尝试动态调用一个外部共享库,它也是用 Rust 编写的。我在发布时编译了外部库,我已经尝试了 cdylibdylib.

这两种板条箱类型

我正在使用 crate libloading,它声称能够动态加载共享库函数,只要它们只使用原始参数。当我尝试使用这个 crate 运行 我的代码时,我不断收到这个错误。

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: GetProcAddress { source: Os { code: 127, kind: Other, message: "The specified procedure could not be found." } }', src\main.rs:14:68
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

main.rs/main():

    let now = Instant::now();

    unsafe {
        let lib = libloading::Library::new(
            "externtest.dll").unwrap();
        let foo3: Symbol<extern fn(i32) -> i32> = lib.get(b"foo").unwrap();

        println!("{}", foo(1));
    }

    let elapsed = now.elapsed();
    println!("Elapsed: {:?}", elapsed);

lib.rs:

pub extern "C" fn foo3(i:i32) -> i32{
    i
}

首先,您的库函数名为 "foo3",但您正在尝试加载符号 "foo"

其次,库函数的符号可能由于重整而与其名称不匹配。您需要告诉编译器不要使用 #[no_mangle] 属性执行此操作:

#[no_mangle]
pub extern "C" fn foo(i: i32) -> i32 {
    i
}

第三,这主要是一种风格选择,但我会在定义符号时指定 ABI extern "C"。尽管 extern with no epecified ABI uses the "C" ABI,我发现还是直截了当更好。

use libloading::{Library, Symbol};

fn main() {
    unsafe {
        let lib = Library::new("externtest.dll").unwrap();
        let foo = lib
            .get::<Symbol<extern "C" fn(i32) -> i32>>(b"foo")
            .unwrap();

        println!("{}", foo(1));
    }
}

以上应该没有问题。