I've tried converting one of my apps from sharedlib
to libloading
. Although I found libloading
's docs unhelpful, I found a useful model here: windows_dpi. This showed how to create the library and its functions as statics which is exactly what I need because my app loads the DLL once and then uses it throughout. (I also tried using normal variables but libloading::Symbol
's need for lifetimes defeated me.) Here's an outline of how I use the library:
use dpl::{self, DPL};
fn main() {
println!("DPL {}", DPL.version());
/// etc.
dpl::close();
}
And here's an outline of how I use libloading
:
use libloading as so;
lazy_static! {
pub static ref DPL: Dpl = Dpl::new().unwrap();
}
pub struct Dpl {
pub instance_id: i32,
}
impl Dpl {
fn new() -> XResult<Dpl> {
let instance_id = CREATE_LIBRARY();
if instance_id == 0 {
xerr!("failed to open PDF library");
}
/// etc
Ok(Dpl { instance_id })
}
/// etc
}
lazy_static! {
pub(crate) static ref LIB: so::Library =
so::Library::new("DebenuPDFLibrary64DLL1612.dll").unwrap();
pub(crate) static ref CREATE_LIBRARY: so::Symbol<'static, SigVrI> =
{ unsafe { LIB.get(b"DPLCreateLibrary\0").unwrap() } };
pub(crate) static ref RELEASE_LIBRARY: so::Symbol<'static, SigIrI> =
{ unsafe { LIB.get(b"DPLReleaseLibrary\0").unwrap() } };
/// etc
}
// MUST call just before program termination!
pub fn close() {
RELEASE_LIBRARY(DPL.instance_id);
}
// Have also tried "stdcall" and "win64"; neither helps
pub(crate) type SigVrI = extern "C" fn() -> i32;
pub(crate) type SigIrI = extern "C" fn(i32) -> i32;
What I've found when I run my automated tests is that I get odd failures when I run them all. However, when I then run the failed tests individually, they almost always work --- none always fail; in fact they normally pass.
So now I'm thinking of reverting back to sharedlib
since that's never given me any reliability problems. But OTOH I like creating the library and its functions statically and would rather that worked.
I'm using Windows 7-64, Rust 1.34.0.