动态链接crate

假设动态库是 impls
需要链接到 impls的crate是abi

├── abi                     # runtime loading library
│  ├── Cargo.toml           # specifies dependent libraries to be used for dynamic linking
│  └── src
│     ├── import.rs         # import impls to this crate
│     ├── lib.rs            # 
│     └── main.rs           # test main: loading abi and binding interface
├── impls                   # dynamic link library 
│  └── src
│     └── lib.rs            # impls
└── README.md

main == loadl ibrary => abi == dynamic link ==> impls

设置lib类型为cdylib

# impls/Cargo.toml
[lib]
crate-type = ["cdylib"]

导出接口

// impls/src/lib.rs
#[no_mangle]
pub extern "C" fn add(left: usize, right: usize) -> usize {
    left + right
}

设置依赖

# abi/Cargo.toml
[dependencies]
impls = { path = "../impls" }

接口定义

#[link(name = "impls")]
extern "C" {
    pub fn add(a :usize, b: usize) -> usize;
}

调用接口

println!("Add {}", add(1, 9));

运行时加载动态库

因为是运行时加载,所以函数的接口不需要单独定义,通常是绑定到函数指针上

# abi/Cargo.toml
[dependencies]
impls = { path = "../impls" }
libloading = "0.8.5"
// abi/src/main.rs
use libloading::{Library, Symbol};

static DLL_HANDLE:Lazy<Library> = Lazy::new(|| {
    unsafe {
        let dll = std::env::args().nth(1).expect("No DLL provided");
        Library::new(dll).expect("Failed to load DLL")
    }
});

// 定义好函数指针的结构体
#[derive(Debug)]
struct Interface<'a> {
    add: Symbol<'a, extern "C" fn(usize, usize) -> usize>,
    init: Symbol<'a, extern "C" fn() -> ()>,
}

// 加载动态库后,绑定函数指针
impl <'a> Interface<'a> {
    fn new() -> Self {
        unsafe {
            let add: Symbol<extern "C" fn(usize, usize) -> usize> = DLL_HANDLE.borrow().get(b"add").expect("Failed to load add");
            let init: Symbol<extern "C" fn() -> ()> = DLL_HANDLE.borrow().get(b"init").expect("Failed to load init");
            Interface {
                add,
                init
            }
        }
    }
}

fn main() {
    let handle = Interface::new();
    (handle.init)();
    let result = (handle.add)(1, 9);
    println!("Result: {}", result);
    
}

Demo

项目地址 Demo