当前位置: 首页 > news >正文

Linux动态库热加载驱动插件机制-示例

🎯 目标

构建一个插件式驱动系统,使主程序能够动态加载外部 .so 驱动,并通过接口调用相应功能。驱动类的注册通过工厂实现,支持 C++ 标准类型和继承体系。


📦 插件机制原理

  • 使用 dlopen() 加载 .so 插件
  • 插件通过静态对象构造自动注册驱动到单例工厂
  • 工厂类存储驱动构造函数(Lambda)
  • 主程序根据名字获取驱动指针并调用接口

🧩 插件结构设计(以相机为例)

1. 驱动接口基类(CameraDriver.h)

#pragma once
#include <vector>
#include <cstdint>class CameraDriver {
public:virtual ~CameraDriver() = default;virtual void start() = 0;virtual std::vector<uint8_t> capture_image() = 0;
};

2. 工厂注册类模板(CameraRegistry.h)

#pragma once
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>template <typename T>
class CameraRegistry {
public:static CameraRegistry& instance() {static CameraRegistry inst;return inst;}void register_driver(const std::string& name, std::function<std::unique_ptr<T>()> creator) {creators_[name] = std::move(creator);}T* get(const std::string& name) {if (creators_.count(name)) {instances_[name] = creators_[name]();return instances_[name].get();}return nullptr;}private:std::unordered_map<std::string, std::function<std::unique_ptr<T>()>> creators_;std::unordered_map<std::string, std::unique_ptr<T>> instances_;
};

3. 插件注册辅助模板(RegisterMacro.h)

#pragma once
#include "CameraRegistry.h"
#include <string>template <typename T>
struct CameraRegister {CameraRegister(const std::string& name) {CameraRegistry<CameraDriver>::instance().register_driver(name, []() {return std::make_unique<T>();});}
};// 使用宏简化写法
#define REGISTER_CAMERA_DRIVER(CLASS) \\static CameraRegister<CLASS> reg_##CLASS(#CLASS);

4. 插件实现(如 libusb_camera.so)

#include "CameraDriver.h"
#include "RegisterMacro.h"
#include <iostream>class UsbCamera : public CameraDriver {
public:void start() override {std::cout << "UsbCamera started\\n";}std::vector<uint8_t> capture_image() override {return {42, 43, 44};}
};REGISTER_CAMERA_DRIVER(UsbCamera)
  • 这里的 REGISTER_CAMERA_DRIVER(UsbCamera) 定义了一个全局静态对象 reg_UsbCamera

  • 动态库被 dlopen 加载时,该静态对象的构造函数会自动执行,完成注册。

  • 主程序无需调用注册函数。

🚀 主程序加载插件并调用

#include "CameraDriver.h"
#include "CameraRegistry.h"
#include <dlfcn.h>
#include <iostream>int main() {void* handle = dlopen("libusb_camera.so", RTLD_LAZY);if (!handle) {std::cerr << "Failed to load plugin: " << dlerror() << "\\n";return 1;}// 不需要 dlsym 调用注册函数,加载动态库时自动注册// 使用注册的驱动CameraDriver* driver = CameraRegistry<CameraDriver>::instance().get("UsbCamera");if (driver) {driver->start();auto img = driver->capture_image();std::cout << "Image size: " << img.size() << "\\n";} else {std::cerr << "Driver not found\\n";}dlclose(handle);return 0;
}

🔧 常用系统函数说明

函数名说明
dlopen加载 .so 文件,返回句柄
dlsym获取动态库中的函数地址
dlclose卸载动态库
dlerror获取最近一次 dl 操作的错误信息
dlmopen支持加载多个命名空间的变种 dlopen

✅ 总结

  • 动态库加载时,全局静态对象构造自动注册驱动。
  • 主程序直接通过工厂单例获取驱动实例。
  • 避免手动调用注册函数和暴露 C 符号。
  • 代码更简洁,符合现代 C++ 插件设计理念。
http://www.xdnf.cn/news/470035.html

相关文章:

  • 国标GB28181视频平台EasyGBS助力智慧医院打造全方位视频监控联网服务体系
  • QML元素 - MaskedBlur
  • 力扣-236.二叉树的最近公共祖先
  • Elasticsearch 常用语法手册
  • 格恩朗椭圆齿轮流量计 工业流量测量的可靠之钥
  • MySQL库的操作
  • 【笔记】CosyVoice 模型下载小记:简单易懂的两种方法对比
  • vacuum、vacuum full的使用方法及注意事项
  • “禁塑行动·我先行”环保公益项目落地宁夏,共筑绿色生活新篇章
  • 4、前后端联调文生文、文生图事件
  • 趋势跟踪策略的回测
  • AI Agent开发第67课-彻底消除RAG知识库幻觉-文档分块全技巧(1)
  • pgsql14自动创建表分区
  • SpringBoot 自动装配流程
  • [Java实战]Spring Boot 3实现 RBAC 权限控制(二十五)
  • SpringBoot项目使用POI-TL动态生成Word文档
  • 去年开发一款鸿蒙Next Os的window工具箱
  • 软考软件评测师——软件工程之系统维护
  • ADS1220高精度ADC(TI)——应用 源码
  • 采用sherpa-onnx 实现 ios语音唤起的调研
  • 每周靶点:NY-ESO-1、GPC3、IL27分享
  • Linux操作
  • Oracle APEX IR报表列宽调整
  • [ctfshow web入门] web75
  • 运维实施30-FTP服务
  • 欧拉计划 Project Euler 73(分数有范围计数)题解
  • ABP User Interface-Angular UI中文详解
  • Loki的部署搭建
  • JS手写代码篇---手写 Object.create
  • 哈夫曼树完全解析:从原理到应用