Rust crate间动态链接可行性咨询:bin与lib运行时链接方法
Rust 动态链接的现状与运行时加载实现
Rust 目前完全支持动态链接,旧资料里“不支持动态链接”的说法早已过时。你提到的 bevy_dylib 这类库,正是基于 Rust 的动态链接能力实现热重载等功能的。
你想要的“运行时将 bin 链接到 lib”属于动态加载(runtime dynamic loading)范畴,和编译时动态链接是两种不同的场景:
- 编译时动态链接:cargo 默认支持,只需将 lib 编译为
dylib格式,bin 依赖该 lib 即可,运行时需要动态库文件存在,但无需在代码里手动加载。 - 运行时动态加载:需要手动通过系统 API 或第三方库加载动态库、查找符号,能实现更灵活的加载逻辑(比如按需加载、热重载)。
以下是具体实现步骤和代码示例:
1. 创建动态库(lib crate)
首先创建一个 lib crate,配置为生成动态库:
# Cargo.toml (lib crate) [package] name = "my_dylib" version = "0.1.0" edition = "2021" [lib] crate-type = ["dylib"] # 指定生成动态库
lib.rs 中导出函数时,必须添加 #[no_mangle] 和 extern "C" 来保证函数名不被混淆、调用约定兼容:
// lib.rs #[no_mangle] pub extern "C" fn hi() { println!("hi"); }
执行 cargo build 后,会在 target/debug 目录生成对应平台的动态库:
- Linux:
libmy_dylib.so - Windows:
my_dylib.dll - macOS:
libmy_dylib.dylib
2. 创建可执行文件(bin crate)并实现运行时加载
使用 libloading 库(跨平台封装了系统动态加载 API)来实现运行时加载:
首先在 bin crate 的 Cargo.toml 添加依赖:
# Cargo.toml (bin crate) [package] name = "my_bin" version = "0.1.0" edition = "2021" [dependencies] libloading = "0.8"
main.rs 中加载动态库并调用函数:
// main.rs use libloading::{Library, Symbol}; fn main() -> Result<(), Box<dyn std::error::Error>> { // 加载动态库,路径根据平台调整 let lib = Library::new("./target/debug/libmy_dylib.so")?; // 查找函数符号,签名必须和库中定义一致 let hi: Symbol<unsafe extern "C" fn()> = lib.get(b"hi")?; // 调用函数,extern "C" 函数需要在 unsafe 块中执行 unsafe { hi(); } Ok(()) }
关键注意点
#[no_mangle]是必须的:Rust 默认会对函数名进行名称混淆,不加这个属性的话,动态加载时找不到对应的符号。extern "C"用于统一调用约定:不同语言/平台的调用约定可能不同,使用 C 调用约定能确保兼容性。- 仅
dylib/cdylib支持动态加载:rlib是 Rust 专用的静态库格式,无法被运行时动态加载;cdylib则是用于给其他语言(如 C)调用的动态库格式,也可用于 Rust 的动态加载。 bevy_dylib的原理:这类库正是通过动态加载dylib实现热重载——在运行时替换动态库文件,重新加载符号,从而实现无需重启程序即可更新代码。
内容的提问来源于stack exchange,提问作者salmon
相关产品推荐
相关产品推荐

