需要加载某个动态库(106kb,C++编写,提供C接口),我发现使用推荐的方法
// loop for 2000
fn call_dynamic(x: Vec<i32>) -> Result<u32, Box<dyn std::error::Error>> {
unsafe {
let lib = libloading::Library::new("/path/to/liblibrary.so")?;
let func: libloading::Symbol<unsafe fn(*const i32) -> u32> = lib.get(b"my_func")?;
Ok(func(x.as_ptr()))
}
}
时,每次调用的时间高达1ms多,其中主要由libloading::Library::new
这个载入动态库的行为占了绝大部分的时间消耗。这个对于我来说是不可容忍的,因为我需要调用这个函数2000次,程序总消耗在6.2s左右,这个函数就占用了接近3秒的时间。也就是有有一半的时间拿来载入动态库了,太浪费时间了。
我唯一想到的办法是:
fn calculator() {
let lib;
let func;
unsafe {
lib = libloading::Library::new("/path/to/liblibrary.so").unwrap();
func: libloading::Symbol<unsafe fn(*const i32) -> u32> = lib.get(b"my_func").unwrap();
}
let ret = call_dynamic(vec![0, 1, 2], func); // loop for 2000
}
fn call_dynamic(x: Vec<i32>, func: Symbol<unsafe fn(*const i32) -> u32>) -> u32 {
unsafe {
func(x.as_ptr())
}
}
但是这个实现我觉得也太丑了吧。而且如上所示,这是一个库,没有入口,假如我需要calculator2()
函数,我又要重复导入。
有没有办法把这个设置成全局变量,然后无论哪个函数,都可以很方便的调用func
啊,类似
// error: calls in constants are limited to constant functions, tuple structs and tuple variants
const lib = Library::new("spsolver.dll").unwrap();
const func = lib.get(b"spsolver_LU").unwrap();
fn call_dynamic(x: Vec<i32>) -> u32 {
unsafe {
func(x.as_ptr())
}
}
显然这个不行,因为Library::new
的签名是pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, Error>
。真的很无语。
求教!有没有办法能像使用自己写的rust函数一样,编译时一次载入动态库,然后处处使用?
1
共 3 条评论, 1 页
评论区
写评论😅
牛啊大佬!一把成功。程序运行时间3.2S左右,与我手写的丑陋的一次载入运行速度完全一致!
万分感谢!!!
--
👇
ywxt: