Linux 动态库热加载

📌 什么是热加载(Hot Reload)

  • 指主程序在不重启的前提下,通过动态方式加载(或重新加载)动态库(.so 文件),使得逻辑可以在运行时替换或更新。
  • 热加载通常需要重新编译 .so,但不需要重新运行主程序

🛠 基本流程

// 加载库
void* handle = dlopen("libplugin.so", RTLD_LAZY);

// 获取函数地址
typedef int (*AddFunc)(int, int);
AddFunc add = (AddFunc)dlsym(handle, "add");

// 使用函数
int result = add(1, 2);

// 卸载库(如需重新加载新版)
dlclose(handle);

🔧 主要系统函数说明(<dlfcn.h>)

函数名作用
dlopen加载动态库,返回句柄 void*
dlsym从句柄中查找符号(函数或变量)地址
dlclose卸载已加载的动态库
dlerror获取最近一次 dlopen / dlsym / dlclose 的错误信息

示例:

void* handle = dlopen("libplugin.so", RTLD_LAZY);
if (!handle) {
    fprintf(stderr, "dlopen error: %s\n", dlerror());
}

⚠️ extern “C” 的必要性

  • C++ 编译器会对函数名做“名称修饰”(name mangling),导致 dlsym 无法识别函数名。
  • 加上 extern "C" 让函数以 C 的方式导出,无名称修饰。
extern "C" int add(int a, int b);

📦 动态库函数的参数设计建议

参数类型是否推荐说明
int, float简单类型,兼容性好
const char*字符串以 C 风格传递
void*通用指针,可用于传结构体地址等
std::string不推荐,C++ 类型,ABI 不稳定
std::vector不推荐,使用裸数组 + size 替代
自定义 struct⚠️结构体需对齐一致、layout 固定

🌀 动态更新库的流程(热加载)

  1. 主程序运行;
  2. 加载 libplugin.so
  3. 程序运行中,卸载该库(dlclose);
  4. 替换或重新编译 libplugin.so
  5. 主程序再次加载,即可使用新逻辑。

🧪 编译示例

1. 动态库(plugin.cpp)

extern "C" int add(int a, int b) {
    return a + b;
}
g++ -fPIC -shared -o libplugin.so plugin.cpp

2. 主程序(main.cpp)

#include <dlfcn.h>
#include <iostream>

typedef int (*AddFunc)(int, int);

int main() {
    void* handle = dlopen("./libplugin.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "dlopen failed: " << dlerror() << std::endl;
        return 1;
    }

    AddFunc add = (AddFunc)dlsym(handle, "add");
    if (!add) {
        std::cerr << "dlsym failed: " << dlerror() << std::endl;
        dlclose(handle);
        return 1;
    }

    std::cout << "1 + 2 = " << add(1, 2) << std::endl;
    dlclose(handle);
    return 0;
}
g++ main.cpp -ldl -o main
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值