DLL-based application framework with bi-directional interfaces (Windows)
Solved
this
wasn't the problem, since it's being implicitly cast to IFramework
anyway.
I was concerned it may have to do with my methods not returning HRESULT
, or with my stubby implementations of IUnknown::QueryInterface
, but the real problem was merely a compiler setting that had overridden several macros I needed for common calling conventions (perhaps I should have included them in the question). This had corrupted the stack.
It's interesting though, that it worked will all compilers I tested, even without implementing IUnknown at all - a little research suggests that all serious Windows compilers handle abstract C++ interfaces the same way - namely as a virtual table specifically to be used as a COM interface.
Hi. I'm trying to create an extensible application framework. My basic concept is this:
The "Framework" box will build an .exe whereas the multiple "Plugin" boxes will build .dll files.
However, my implementation is apparently flawed. I have an idea what's the problem, but I'm running out of workarounds. I've done it exactly like this with .NET projects, but the problem I have now didn't apply to the C# environment.
Consider these interfaces:
class IFramework
{
public:
virtual void FrameworkMethod() = 0;
};
class IPlugin
{
public:
virtual void PluginMethod() = 0;
virtual void PluginCallbackTest() = 0;
virtual void SetFramework(IFramework *framework) = 0;
};
Implementation of the framework:
class CFramework : IFramework
{
public:
void FrameworkMethod(); // printf("FrameworkMethod");
void DoSomething(); // this is the testbench basically, see below
};
And the implementation of the plugin:
class CPlugin : public IPlugin
{
IFramework *Framework;
public:
void PluginMethod(); // printf("PluginMethod");
void PluginCallbackTest(); // Framework->FrameworkMethod();
void SetFramework(IFramework *framework); // Framework = framework;
};
// plugin factory -> COM interface
extern "C" PLUGIN_API IPlu开发者_运维知识库gin *GetPlugin(); // return new CPlugin;
Now to demonstrate that this concept doesn't work:
void CFramework::DoSomething()
{
HMODULE PluginHandle = LoadLibrary(...); // explicit linking
auto GetPlugin = ((IPlugin *)(*)())GetProcAddress(...);
IPlugin *plugin = GetPlugin();
plugin->PluginMethod();
// up until here everything's perfectly COM-compliant and works super
plugin->SetFramework(this); // <-- that is the problem
plugin->PluginCallbackTest(); // <-- runtime crash if compiler differs
FreeLibrary(PluginHandle);
}
The problem is that the SetFramework(this)
doesn't work like COM. It's not that it just feels wrong to write it like this - I can't implement a working plugin with a compiler that differs from the one I used to build CFramework (runtime crashes).
If you want to allow different compilers for the plug-ins from what you use for the app then you need to use COM exclusively across the boundary between app and plug-ins. That is precisely the problem that COM was designed to solve.
精彩评论