您当前的位置: 首页 >  c++
  • 1浏览

    0关注

    483博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

VC++写一个演示如何为应用程序写plugin插件的项目

高精度计算机视觉 发布时间:2020-08-10 13:21:27 ,浏览量:1

如果不需要plugin,DLL一般都是带lib直接编译进项目的居多,这种情况下,和普通的函数库调用没什么区别。

但如果考虑到自己的应用程序中,要允许客户中任何人添加plugin,那情况就有所不同。

这里(参考地址:http://www.cplusplus.com/articles/48TbqMoL/)给出了一个用MINGW编译的例子,但这个例子在VC上是运行不通的。我稍加修改,并作了备注,做成了一个VCC演示工程。main.hpp中例出了3种情况,

(1)extern "C" __declspec(dllimport/dllexport)的C程序格式

(2)__declspec(dllimport/dllexport),可调用C++类的程序格式

(3)*.def定义的形式

#ifndef __MAIN_HPP_INCLUDED__
#define __MAIN_HPP_INCLUDED__

#include 
#include 

/*
method (1)Only suitable for C type, NOT c++ classes
    #define DLLAPI extern "C" __declspec(dllexport)

method (2) for compile with test1.lib / test2.lib / test3.lib etc.
    #define DLLAPI __declspec(dllexport)

    NOTE: if your application is not compiled with *.lib, and you need to use loadlibrary, the format may be strange as below

    typedef std::unique_ptr (__cdecl *ObjProc)(void);
    HINSTANCE mod = LoadLibrary("test1.dll");
    ObjProc objFunc = (ObjProc) GetProcAddress(mod, "?getObj@@YA?AV?$unique_ptr@VBase@@U?$default_delete@VBase@@@std@@@std@@XZ");

    the strange name ""?getObj@@YA?AV?$unique_ptr..." can be obtained from dumpbin tool
    dumpbin /exports test1.dll
    
method (3) plugin mode
    #define DLLAPI

    NOTE: in this case you need to define the source.def file, the contents may be as below,

    LIBRARY TEST1
    EXPORTS
    getObj
    getName
    getValue
*/

#ifdef _WINDLL // BUILD_DLL for MINGW
    //#define DLLAPI extern "C" __declspec(dllexport)
    //#define DLLAPI __declspec(dllexport)
    #define DLLAPI
#else
    //#define DLLAPI extern "C" __declspec(dllimport)
    //#define DLLAPI __declspec(dllimport)
    #define DLLAPI
#endif // BUILD_DLL


class Base {
public:
    virtual ~Base() = default;
    virtual void print(void) = 0;
    virtual double calc(double val) = 0;
};

// DLL export funcs

DLLAPI std::unique_ptr getObj(void);
DLLAPI std::string getName(void);
DLLAPI int getValue(void);

#endif // __MAIN_HPP_INCLUDED__

主要定义上变化的部分就在这里,其他内容就不再解释了,和原贴基本没什么区别,其实都很简单,例如main.cpp只添加了一个测试getValue函数,

// Program to demonstrate the use of a plugin system.

#include 
#include 
#include 
#include 
#include 
#include 
#include "main.hpp"

// Load the objects from the plugin folder.
//
// Takes as a parameter a reference to a list of modules,
// which will be emptied and then refilled with handles to
// the modules loaded. These should be freed with the
// FreeLibrary() after use.
//
// Returns a list of Base*, contained in a smart pointer
// to ease memory deallocation and help prevent memory
// leaks.
std::vector getPlugins(std::vector& modules) {
    // A temporary structure to return.
    std::vector ret;
    // empty the modules list passed
    modules.clear();

    // Find the files contained in the 'plugins' folder
    WIN32_FIND_DATA fileData;
    HANDLE fileHandle = FindFirstFile(R"(.\plugins\*.dll)", &fileData);

    if (fileHandle == (void*)ERROR_INVALID_HANDLE ||
        fileHandle == (void*)ERROR_FILE_NOT_FOUND) {
        // If we couldn't find any plugins, quit gracefully,
        // returning an empty structure.
        return std::vector();
    }

    // Loop over every plugin in the folder and store in our
    // temporary return list
    do {
        // Define the function types for what we are retrieving
        typedef std::unique_ptr (__cdecl *ObjProc)(void);
        typedef std::string (__cdecl *NameProc)(void);
        typedef int (__cdecl *valueProc)(void);

        // Load the library
        HINSTANCE mod = LoadLibrary((R"(.\plugins\)" + std::string(fileData.cFileName)).c_str());

        if (!mod) {
            // Couldn't load the library, cleaning module list and quitting.
            for (HINSTANCE hInst : modules)
                FreeLibrary(hInst);
            throw std::runtime_error("Library " + std::string(fileData.cFileName) + " wasn't loaded successfully!");
        }

        // Get the function and the class exported by the DLL.
        // If you aren't using the MinGW compiler, you may need to adjust
        // this to cope with name mangling (I haven't gone into this here,
        // look it up if you want).
        ObjProc objFunc = (ObjProc) GetProcAddress(mod, "getObj");
        int ecode = GetLastError();
        NameProc nameFunc = (NameProc) GetProcAddress(mod, "getName");
        ecode = GetLastError();
        valueProc valueFunc = (valueProc)GetProcAddress(mod, "getValue");
        ecode = GetLastError();


        if (!objFunc || !nameFunc)
            throw std::runtime_error("Invalid Plugin DLL: both 'getObj' and 'getName' must be defined.");

        // push the objects and modules into our vectors
        ret.push_back(objFunc());
        modules.push_back(mod);

        std::clog             
关注
打赏
1661664439
查看更多评论
0.0419s