C++插件管理类(下)——实际项目(阉割版)

简介: C++插件管理类(下)——实际项目(阉割版)

@[toc]

一、背景

请参考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 {
   
   mathJaxContainer[1]}{
   
   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宏去限定生成目录
在这里插入图片描述

七、 项目地址

地址

相关文章
|
2天前
|
测试技术 C++
C++|运算符重载(3)|日期类的计算
C++|运算符重载(3)|日期类的计算
|
3天前
|
C语言 C++ 容器
C++ string类
C++ string类
9 0
|
4天前
|
C++ Linux
|
4天前
|
存储 C++ UED
【C++】飞机大战项目记录
通过上面的设计,我们实现来看飞机大战的主要功能
25 4
|
4天前
|
编译器 C++
【C++】继续学习 string类 吧
首先不得不说的是由于历史原因,string的接口多达130多个,简直冗杂… 所以学习过程中,我们只需要选取常用的,好用的来进行使用即可(有种垃圾堆里翻美食的感觉)
9 1
|
4天前
|
算法 安全 程序员
【C++】STL学习之旅——初识STL,认识string类
现在我正式开始学习STL,这让我期待好久了,一想到不用手撕链表,手搓堆栈,心里非常爽
16 0
|
4天前
|
存储 安全 测试技术
【C++】string学习 — 手搓string类项目
C++ 的 string 类是 C++ 标准库中提供的一个用于处理字符串的类。它在 C++ 的历史中扮演了重要的角色,为字符串处理提供了更加方便、高效的方法。
18 0
【C++】string学习 — 手搓string类项目
|
4天前
|
Java C++ Python
【C++从练气到飞升】06---重识类和对象(二)
【C++从练气到飞升】06---重识类和对象(二)
|
4天前
|
编译器 C++
【C++从练气到飞升】06---重识类和对象(一)
【C++从练气到飞升】06---重识类和对象(一)