最近需要使用Rust动态调用动态链接库,本来打算是使用libloading
的,但是libloading
在调用dll中的函数的时,是必须要在编译时确定参数和return的类型的。但后来发现了libloader
这个包包,libloader
是基于libloading
的,但是操作起来却比libloader
方便。
我们先需要一个动态链接库,我们可以使用cargo create project-name --lib
创建一个动态链接库的项目,然后修改lib.rs
后使用cargo build
编译,我写了三种类型的函数
// lib.rs
#[no_mangle]
pub fn println(str: &str) { // 有参数没有返回值
println!("{}", str);
}
#[no_mangle]
pub fn add(a: usize, b: usize) -> usize { // 有参数有返回值
a + b
}
#[no_mangle]
pub fn print_hello() { // 没有参数没有返回值
println!("Hello");
}
然后再用cargo create project-name --bin
创建一个使用dll的项目
我们把编译出的动态链接库复制到新项目的根目录,我的链接库的名称是libstd.dylib
,.dylib
是macOS编译出的链接库,如果你使用的是Linux或者Windows,则后缀名会是.so
和.dll
然后我们需要安装libloader的依赖,我们在Cargo.toml
中的[dependencies]
下添加libloader: "0.1.4"
[dependencies]
libloader: "0.1.4"
目前的最新版本是0.1.4
,建议使用最新版本,最新版本可以在这里查看:libloader - crates.io: Rust Package Registry
我们现在来写main.rs
的代码
我们需要先引用libloader
内置的libloading
,这侧面印证了libloader是基于libloading的
use libloader::libloading
然后我们需要获取动态链接库中的函数,其中每个参数的作用已经在代码的注释标识了,值得注意的是,如果函数没有返回值,则可以用()
代替。
get_libfn!("libstd.dylib", "println", my_println, (), str: &str); // 获取dll的函数
// ^链接库路径 ^库中的函数 ^调用的名称 ^返回值 ^参数
下一步我们可以直接调用之前传给get_libfn
的"调用的名字"
my_println("Hello World"); // 输出 Hello World
其它函数也是一样,完整代码为:
// main.rs
use libloader::libloading // 首先需要引用libloader的libloading,侧面印证了libloader是基于libloading的
fn main() {
get_libfn!("libstd.dylib", "println", my_println, (), str: &str); // 获取dll的函数
// ^链接库路径 ^库中的函数 ^调用的名称 ^返回值 ^参数
my_println("Hello World");
get_libfn!("libstd.dylib", "add", my_add, usize, a: usize, b: usize);
println!("10 + 20 = {}", my_add(10, 20));
get_libfn!("libstd.dylib", "print_hello", my_print_hello, ());
my_print_hello();
}
导航:
- libloader的crates.io: libloader - crates.io: Rust Package Registry
- libloader的Github: Qixinies/libloader: A easy-to-use dll loader for rust that based on libloading (github.com)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。