文章目录
- 一、背景
- 二、代码结构
- 三、两个CMakeLists.txt
- 3.1 父目录
- 3.2 子目录src
- 四、代码实例
- 4.1 main.cpp
- 4.2 Plugin.h
- 4.3 Plugin.cpp
- 4.4 Comm.h
- 4.5 calc.cpp
- 五、 踩坑点
一、背景
请参考C++插件管理类(上)
二、代码结构
三、两个CMakeLists.txt
3.1 父目录
#设置cmake的最低版本
cmake_minimum_required(VERSION 3.10)
# Set CMAKE_SKIP_BUILD_RPATH to TRUE
# 设置工程的名称
project(PluginManagers)
# 设置库和可执行文件的输出目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_subdirectory(src)
# 将源代码添加到工程生成可执行文件
add_executable(PluginManagers main.cpp Plugin.h Plugin.cpp Comm.h)
3.2 子目录src
cmake_minimum_required(VERSION 3.0)
message("${CMAKE_BINARY_DIR}/${IDE_BIN_DIR}")
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${IDE_BIN_DIR})
add_library(calcu SHARED "calcu.cpp")
四、代码实例
4.1 main.cpp
#include<iostream>
#include <vector>
#include "Plugin.h"
#include "Comm.h"
using namespace std;
typedef int (*_add_function_)(int a, int b);
typedef int (*_sub_function_)(int a, int b);
int main()
{
PluginMannager plug;
if (FAILURE == plug.tuiLoadPlugin("calcu"))
{
cout << "Has No DLL" << endl;
}
void* func = nullptr;
if (FAILURE == plug.getFunction(func, ADD_FUNCTION))
{
return false;
}
int Sum=((_add_function_)func)(1,2);
cout << "Sum is:" << Sum << endl;
if (FAILURE == plug.getFunction(func, SUB_FUNCTION))
{
return false;
}
int Sub= ((_sub_function_)func)(1, 2);
cout << "Sub is:" << Sub << endl;
return 0;
}
4.2 Plugin.h
#include<iostream>
#include <vector>
using namespace std;
typedef void* PluginHandle;
typedef struct PluginInterfaceInformatin
{
string dllName = "";
string version = "";
string interfaceName = "";
PluginHandle function = NULL;
int type = -1;
}PluginInfo;
using PluginInfoVector = std::vector<PluginInfo>;
class Plugin
{
public:
bool Init(const std::string& filename);
bool Execute(void* &func, int type);
private:
PluginHandle handle = nullptr;
PluginInfoVector EntryVector;
};
class PluginMannager
{
public:
/*加载插件*/
bool tuiLoadPlugin(const std::string& filename);
/*获取函数指针*/
bool getFunction(void*& func, int type);
private:
/*插件库*/
std::vector<Plugin> pluginList;
};
4.3 Plugin.cpp
#include "Plugin.h"
#include "Comm.h"
#include <Windows.h>
bool Plugin::Init(const std::string& filename)
{
PluginHandle handle = nullptr;
handle = LoadLibrary(filename.c_str());
if (handle == nullptr)
return FAILURE;
this->handle = handle;
this->EntryVector.swap(*(PluginInfoVector*)GetProcAddress((HMODULE)handle, str(plugins)));
return SUCCESS;
}
bool Plugin::Execute(void* &func, int type)
{
for (auto& entry : this->EntryVector)
{
if(type == entry.type)
{
func = entry.function;
return SUCCESS;
}
}
return 0;
}
bool PluginMannager::tuiLoadPlugin(const std::string& filename)
{
Plugin plug;
if (FAILURE == plug.Init(filename))
{
return FAILURE;
}
this->pluginList.push_back(plug);
return SUCCESS;
}
bool PluginMannager::getFunction(void*& func, int type)
{
for (auto& plug : pluginList)
{
if (SUCCESS == plug.Execute(func, type))
{
return SUCCESS;
}
else
{
return FAILURE;
}
}
return SUCCESS;
}
4.4 Comm.h
#if (_WIN32) || (_WIN64)
#define PLUGIN_EXPORT extern "C" _declspec(dllexport)
#else
#define PLUGIN_EXPORT exter "C"
#endif
typedef enum PLUGIN_FUN_TYPE
{
ADD_FUNCTION = 0,
SUB_FUNCTION
};
#define __data__ plugins
#define PLUGIN_DATA(...) PluginInfoVector __data__={__VA_ARGS__}
#define PLUGIN_DEFINE \
PLUGIN_EXPORT PluginInfoVector __data__ ;\
#define str(e) #e
#define SUCCESS 0
#define FAILURE 1
4.5 calc.cpp
#include "../Plugin.h"
#include "../Comm.h"
PLUGIN_DEFINE
int add(int x, int y)
{
return x + y;
}
int sub(int x, int y)
{
return x - y;
}
PLUGIN_DATA({ "calc", "1.0","add",(void*)add, ADD_FUNCTION }
,{ "calc", "1.0","sub",(void*)sub, SUB_FUNCTION });
五、 踩坑点
🎈:可执行文件和库文件需要再同一文件目录下:所以需要使用CMake宏去限定生成目录