[英]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。
在最高級別上,預期的行為是:
API.dll
加載插件目錄(例如plugin/plugin1.dll
和plugin/plugin2.dll
) API.dll
通過抽象類的getPlugin()
創建插件的單例實例 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.