You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 14:42:36