Original Post
Hey guys,
So I have a base class which defines my plugin interface
This is inherited by all plugins. So, for example, one of my plugins (which are DLLs):
Note that last line, which is an additional requirement for all plugins.
Okay, so back in the executable again, I have a plugin manager class. One routine in that class is to load the plugins. I'm going to abbreviate this somewhat for space
Note those last four lines, especially the last two. Obviously this is just test code, I'm not really going to be calling OnLoad() twice. I'm just trying to see what is going on here.
This line:
Plug->OnLoad(PluginName, AddToEngineMenu, PerFrame);
works just fine. The variable Plug has four members in a __vfptr table, corresponding to the four virtual members of that base class, and I can call on any of those members, works great.
However, the plugin manager isn't supporting just one plugin, I need an arbitrary number of plugins (one for each DLL that exists in the plugin folder for the project). So, I pushed plug onto an array (same as a vector for you STL types) which is part of the manager class (again, which I am shortening for space):
Okay, seems like it ought to work fine. But when I try to use that array to call functions, like I've done in the test code:
Plugin[Plugin.Size()-1]->OnLoad(PluginName, AddToEngineMenu, PerFrame);
I get an access violation error. And it turns out that Plugin[0] (which is the first plugin, obviously) has only one member in it's __vvfptr table, and it is not the same address as any of the vtable members of Plug.
So what arcane concept of C++ am I missing here? I thought if I stored a pointer to the plugin, that should give me access to its vtable as well, but that doesn't seem to be the case. Any advice on how to solve this?
So I have a base class which defines my plugin interface
class PluginInterface
{
public:
virtual void OnLoad(String *PluginName, bool *AddToEngineMenu, bool *PerFrame) = 0;
virtual void OnExecute() = 0;
virtual void OnFrameDraw() = 0;
virtual void OnDestroy() = 0;
};
This is inherited by all plugins. So, for example, one of my plugins (which are DLLs):
class FontBuilder : public PluginInterface
{
public:
virtual void OnLoad(String *PluginName, bool *AddToEngineMenu, bool *PerFrame);
virtual void OnExecute();
virtual void OnFrameDraw();
virtual void OnDestroy();
private:
void BuildFontBitmap();
void CreateMaterial();
void *FontTexture;
};
extern "C" { DLLEXPORT PluginInterface* CreatePlugin() { return new FontBuilder(); }}
Note that last line, which is an additional requirement for all plugins.
Okay, so back in the executable again, I have a plugin manager class. One routine in that class is to load the plugins. I'm going to abbreviate this somewhat for space
void PluginManager::LoadPlugin(String PluginFile, String *PluginName, bool *AddToEngineMenu, bool *PerFrame)
{
FARPROC Create;
DWORD Error;
LPVOID lpMsgBuf;
HMODULE NewModule;
PluginInterface *Plug;
NewModule = LoadLibraryW(PluginFile.c_strW());
if (NewModule == nullptr)
{
//error stuff
}
Create = GetProcAddress(NewModule, "CreatePlugin");
if (Create == nullptr)
{
//error stuff
}
Plug = reinterpret_cast<PluginInterface*>(Create());
Plugin.Push_Back(Plug);
Plug->OnLoad(PluginName, AddToEngineMenu, PerFrame);
Plugin[Plugin.Size()-1]->OnLoad(PluginName, AddToEngineMenu, PerFrame);
}
Note those last four lines, especially the last two. Obviously this is just test code, I'm not really going to be calling OnLoad() twice. I'm just trying to see what is going on here.
This line:
Plug->OnLoad(PluginName, AddToEngineMenu, PerFrame);
works just fine. The variable Plug has four members in a __vfptr table, corresponding to the four virtual members of that base class, and I can call on any of those members, works great.
However, the plugin manager isn't supporting just one plugin, I need an arbitrary number of plugins (one for each DLL that exists in the plugin folder for the project). So, I pushed plug onto an array (same as a vector for you STL types) which is part of the manager class (again, which I am shortening for space):
class PluginManager
{
private:
Array <PluginInterface*> Plugin;
};
Okay, seems like it ought to work fine. But when I try to use that array to call functions, like I've done in the test code:
Plugin[Plugin.Size()-1]->OnLoad(PluginName, AddToEngineMenu, PerFrame);
I get an access violation error. And it turns out that Plugin[0] (which is the first plugin, obviously) has only one member in it's __vvfptr table, and it is not the same address as any of the vtable members of Plug.
So what arcane concept of C++ am I missing here? I thought if I stored a pointer to the plugin, that should give me access to its vtable as well, but that doesn't seem to be the case. Any advice on how to solve this?