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++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
61 2
|
2月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
113 5
|
2月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
111 4
|
2月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
151 4
WK
|
2月前
|
机器学习/深度学习 人工智能 算法
那C++适合开发哪些项目
C++ 是一种功能强大、应用广泛的编程语言,适合开发多种类型的项目。它在游戏开发、操作系统、嵌入式系统、科学计算、金融、图形图像处理、数据库管理、网络通信、人工智能、虚拟现实、航空航天等领域都有广泛应用。C++ 以其高性能、内存管理和跨平台兼容性等优势,成为众多开发者的选择。
WK
99 1
|
3月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
35 4
|
3月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
33 4
|
3月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
31 1
|
3月前
|
Ubuntu Linux 编译器
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
通过以上步骤,您已经成功在Ubuntu系统下的VS Code中配置了C/C++项目环境,并能够调用OpenCV库进行开发。请确保每一步都按照您的系统实际情况进行适当调整。
700 3
|
3月前
|
存储 编译器 C语言
【C++打怪之路Lv3】-- 类和对象(上)
【C++打怪之路Lv3】-- 类和对象(上)
24 0