开发者

DLL-based application framework with bi-directional interfaces (Windows)

开发者 https://www.devze.com 2023-02-20 04:54 出处:网络
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 I

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:

DLL-based application framework with bi-directional interfaces (Windows)

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消