簡體   English   中英

如何在C ++中從dll實例化類?

[英]How can I instantiate a class from a dll in C++?

我正在為插件開發人員編寫API,以便他們可以通過我的API訪問應用程序的SDK。 我的API在頭文件中提供了一個宏和抽象類*,plugin-devs必須包含該宏和抽象類以從抽象基類繼承並實現必要的功能(*請參見下面的代碼)。

關於當前問題的研究,我通讀了許多MSDN和stackoverflow文章,發現這些文章最相關:

這個問題是關於您希望插件開發人員在創建其.dll文件時實現的繼承的抽象類/接口的實例。

也許我的方法是不正確的,我已經陷入困境,但是像Reflections和/或COM這樣的事情似乎是我應該做的……只有COM對於此操作似乎顯得過大,因為應用程序將在客戶端運行。 關於C ++ / CLI Reflections的這篇文章似乎很有希望,但是我正在Visual Studio中使用C ++ 17。

在最高級別上,預期的行為是:

  1. API.dll加載插件目錄(例如plugin/plugin1.dllplugin/plugin2.dll
  2. API.dll通過抽象類的getPlugin()創建插件的單例實例
  3. 調用由插件實現的其他方法,值得注意的是load()

因此,這里有一些有關插件開發人員使用API​​的背景設置信息。 該API為接口/抽象類的開發人員提供了標頭,並提供了在宏中創建單例的方法。

API: baseplugin.hpp

#ifdef BUILDINGAPI
#define PLUGINIMPORT 
#define PLUGINEXPORT  __declspec(dllimport)
#else
#define PLUGINIMPORT  __declspec(dllimport)
#define PLUGINEXPORT  __declspec(dllexport)
#endif

// Long macro defined here for creating/deleting singleton
#define PLUGIN(classType)                                           \
static std::shared_ptr<classType> singleton;                        \
extern "C" {                                                        \
    PLUGINEXPORT uintptr_t getPlugin()                                  \
    {                                                               \
        if(!singleton) {                                            \
            singleton = std::shared_ptr<classType>(new classType());\
        }                                                           \
        return reinterpret_cast<std::uintptr_t>(&singleton);        \
    }                                                               \
    PLUGINEXPORT void erasePlugin() {                               \
        if(singleton)                                               \
            singleton = nullptr;                                    \
      }                                                             \
}

// Abstract class defined here:

class PLUGINEXPORT baseplugin
{
public:
    virtual void load() = 0;
    virtual void unload() = 0;
};

因此,插件開發人員可以使用以下方法快速創建插件:

插件: plugin1.hpp

class plugin1: public baseplugin
{
public:
    virtual void load();
    virtual void unload();
// other useful plugin methods/vars
}

插件: plugin1.cpp

PLUGIN(plugin1) // This creates getPlugin() and erasePlugin()
void plugin1::load() {
// do stuff
}
void plugin1::unload() {
// do stuff
}
// other functions

現在,我剩下的工作是加載編碼/構建API.dll以加載插件API.dll的目錄。 這是我當前的代碼,我意識到不知道RTTI是行不通的:

API:dllmain.cpp

typedef uintptr_t(*pFunc)();
HINSTANCE hinstLib = LoadLibrary(TEXT("plugin1.dll"));
if (hinstLib != NULL) {
    FARPROC ProcAdd = GetProcAddress(hinstLib, "getPlugin"); // address to singeleton function
    // If the function address is valid, call the function.  
    if (NULL != ProcAdd) {
        pFunc pPluginSingleton = (pFunc) ProcAdd;
        baseplugin* plugin1Singleton = (baseplugin*) pPluginSingleton(); // THIS LINE WORKS, I GET A POINTER TO A SINGLETON
        plugin1Singleton->load(); // THIS CRASHES!!!! 

在這里可能值得注意的是,使用API.dll的代碼構建plugin1.dll可以正常工作。 我現在正在測試/弄清楚如何在運行時加載插件類型。 我已經驗證了可以使用調試器獲取指向單例的指針,但是在將其強制轉換為抽象類后嘗試運行load方法時,我崩潰了: 0xC0000005: Access violation executing location 0x80B1CCDC

您的應用程序對插件中定義的具體類型一無所知。 它只能對應用程序中定義的類進行操作。 每個插件都需要提供一個工廠方法,該方法可以創建插件中定義的具體類型的實例,並返回指向應用程序中定義的抽象類的指針。 像這樣在Plugin1.dll定義的Plugin1.dll

baseplugin* PLUGINEXPORT create_plugin()
{
    return new plugin1;
}

在您的應用程序中,您可以動態加載Plugin1.dll ,獲取create_plugin函數的地址,然后調用它以獲取plugin1類的實例作為指向baseplugin抽象類的指針。

實現插件API的一種好方法是在boost :: dll的幫助下。 它提供了一些有用的工具來實現插件機制。 例如, 在plugin中Factory方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM