标准C++应用插件封装及泛型动态加载实现(谷歌C++规范)

目录

 

1 概述

2 插件封装

3 插件加载


1 概述

应用模块化难免会使用插件的方式,这里使用纯C++方式实现插件的封装,及插件加载器泛型动态加载。按照这种套路,可以封装及批量加载不同类型的自定义插件。

2 插件封装

需要注意的是,这里的插件是以动态库的形式导出。

2.1 定义插件类型为module_plugin的插件基类

modulebase.h

// modulebase.h
// ...
//
// Created by xxx on 2021/3/28.
// Copyright 2021 xxx, Inc. All rights reserved.
//
#ifndef MIDDLEWARE_MODULE_MODULEBASE_H_
#define MIDDLEWARE_MODULE_MODULEBASE_H_

#include <string>

namespace module {

static const char g_module_plugin_type[] = "module_plugin";

class ModuleBase {
 public:
  explicit ModuleBase(const std::string name)
      : name_(name) {
  }
  virtual ~ModuleBase() {}
  std::string name() const { return name_; }
  void set_name(std::string name) { name_ = name; }
  virtual void Test() = 0;
 private:
  std::string name_;
};

}  // namespace module

#endif  // MIDDLEWARE_MODULE_MODULEBASE_H_

2.2 radiomodule插件

radiomodule.h

// radiomodule.h
// ...
//
// Created by xxx on 2021/3/28.
// Copyright 2021 xxx, Inc. All rights reserved.
//
#ifndef MIDDLEWARE_MODULE_RADIOMODULE_RADIOMODULE_H_
#define MIDDLEWARE_MODULE_RADIOMODULE_RADIOMODULE_H_

#include <memory>
#include "middleware/module/modulebase.h"

namespace module {

class RadioModule : public ModuleBase {
 public:
  RadioModule();
  ~RadioModule();
  virtual void Test();

  // Factory method
  static RadioModule *Create() {
    return new RadioModule();
  }
};

extern "C" const char *Type() {
  return g_module_plugin_type;
}

extern "C" void* Create() {
  return module::RadioModule::Create();
}

}  // namespace module

#endif  // MIDDLEWARE_MODULE_RADIOMODULE_RADIOMODULE_H_

radiomodule.cpp

// radiomodule.cpp
// ...
//
// Created by xxx on 2021/3/28.
// Copyright 2021 xxx, Inc. All rights reserved.
//
#include "middleware/module/radiomodule/radiomodule.h"
#include "apis/logger/logger.h"

namespace module {

RadioModule::RadioModule()
    : ModuleBase("radio_module") {
}

RadioModule::~RadioModule() {
}

void RadioModule::Test() {
  LOGGING->Log(L_INFO , "%s" , __FUNCTION__);
}

}  // namespace module

2.3 bluetoothmodule插件

bluetoothmodule.h

// bluetoothmodule.h
// ...
//
// Created by xxx on 2021/3/28.
// Copyright 2021 xxx, Inc. All rights reserved.
//
#ifndef MIDDLEWARE_MODULE_BLUETOOTHMODULE_BLUETOOTHMODULE_H_
#define MIDDLEWARE_MODULE_BLUETOOTHMODULE_BLUETOOTHMODULE_H_

#include <memory>
#include "middleware/module/modulebase.h"

namespace module {

class BlueToothModule : public ModuleBase {
 public:
  BlueToothModule();
  ~BlueToothModule();
  virtual void Test();

  // Factory method
  static BlueToothModule *Create() {
    return new BlueToothModule();
  }
};

extern "C" const char *Type() {
  return g_module_plugin_type;
}

extern "C" void* Create() {
  return module::BlueToothModule::Create();
}

}  // namespace module

#endif  // MIDDLEWARE_MODULE_BLUETOOTHMODULE_BLUETOOTHMODULE_H_

bluetoothmodule.cpp

// bluetoothmodule.cpp
// ...
//
// Created by xxx on 2021/3/28.
// Copyright 2021 xxx, Inc. All rights reserved.
//
#include "middleware/module/bluetoothmodule/bluetoothmodule.h"
#include "apis/logger/logger.h"

namespace module {

BlueToothModule::BlueToothModule()
    : ModuleBase("bluetooth_module") {
}

BlueToothModule::~BlueToothModule() {
}

void BlueToothModule::Test() {
  LOGGING->Log(L_INFO , "%s" , __FUNCTION__);
}

}  // namespace module

3 插件加载

3.1 插件加载器

pluginloader.h

// pluginloader.h
// ...
//
// Created by xxx on 2021/3/28.
// Copyright 2021 xxx, Inc. All rights reserved.
//
#ifndef APIS_PLUGINLOADER_H_
#define APIS_PLUGINLOADER_H_

#include <dlfcn.h>
#include <dirent.h>
#include <vector>
#include <string>
#include <memory>
// #include "apis/logger/logger.h"

namespace api {

typedef void* PluginCreate();
typedef const char *PluginType();

template <class T>
void LoadPlugins(
    std::string path,
    std::string type,
    std::vector<std::shared_ptr<T>> *plugin_vector) {

  if (nullptr == plugin_vector)
    return;
  DIR *plugins_dir = opendir(path.c_str());
  if (plugins_dir == nullptr) {
    // LOGGING->Log(L_WARNING, "open path %s failed." , path.c_str());
    return;
  }

  // LOGGING->Log(L_DEBUG,
  //              "enter path (%s) ,load plugins (%s).",
  //              path.c_str(),
  //              type.c_str());
  struct dirent *file_info = nullptr;
  while ((file_info = readdir(plugins_dir)) != nullptr) {
    std::string file_name(file_info->d_name);
    int pos = file_name.find_last_of('.');
    std::string suffix = pos >= 0? file_name.substr(pos) : "";
    if (suffix == ".so") {
      std::string file_path = path + "/" + file_name;

      try {
        void* handle = dlopen(file_path.c_str() , RTLD_LAZY);
        if (nullptr == handle) {
          // LOGGING->Log(L_DEBUG , "error: %s" , dlerror());
          continue;
        }

        PluginType* type_func = reinterpret_cast<PluginType*>(
          dlsym(handle , "Type"));
        if (nullptr == type_func) {
          dlclose(handle);
          continue;
        }
        if (type != type_func()) {
          dlclose(handle);
          continue;
        }

        PluginCreate* create_func = reinterpret_cast<PluginCreate*>(
          dlsym(handle , "Create"));
        if (nullptr == create_func) {
            dlclose(handle);
            continue;
        }
        // LOGGING->Log(L_DEBUG,
        //              "load plugin (%s) sucssesed.",
        //              file_path.c_str());

        std::shared_ptr<T> plugin;
        plugin.reset(static_cast<T*>(create_func()));
        plugin_vector->push_back(plugin);
      } catch ( const std::exception & ex ) {
          // LOGGING->Log(L_ERROR , "error: %s" , ex.what());
          continue;
      }
    }
  }
}

}  // namespace api

#endif  // APIS_PLUGINLOADER_H_

3.2 加载调用示例

// other
#include "middleware/module/modulebase.h"
#include "apis/pluginloader.h"
// other

// other
  std::vector<std::shared_ptr<ModuleBase>> module_vector;  
  std::string plugin_path = "./plugins/module";

  api::LoadPlugins(plugin_path,
    "module_plugin",
    &module_vector);
// other

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值