我正在尝试为我的C ++代码库添加插件功能。由于插件需要包含插件编写者不应该知道的管道(因此保持包含文件简单),因此出现了困难。 所以,这是设置:
" PluginBase.h&#34 ;.这是插件将继承的类。
class PluginBase {
virtual void PluginProcess() = 0; // the plugin-specific capability
};
" PluginPlumbing.h&#34 ;.包含管道的类。
class PluginPlumbing : public PluginBase {
void PlumbingFunction() {
// Some stuff
PluginProcess();
// Some more stuff
}
};
外部框架代码(通过加载插件的DLL /)获取指向PluginPlumbing类实例的指针,然后在其上调用PlumbingFunction()。
然而,我遇到的难题是,我不能将我从DLL中获得的PluginBase指针向上转换为PluginPlumbing指针,因为它显然不会从PluginPlumbing继承。而且我无法从PluginPlumbing继承插件,因为我回到了将插件暴露给插件编写器的方方面面。
我能想象的唯一解决方案是,PluginBase和PluginPlumbing完全是独立的类,而不是很好地继承。 PluginBase将由DLL / so实例化,PluginPlumbing实例将由框架实例化,并传递PluginBase指针,以便它可以进行管道调用。这是解决问题的唯一解决方案吗?
答案 0 :(得分:0)
如果您想将插件中的某些功能暴露给外部软件,您必须提供一些接口。
在您的示例中,您提供了PluginBase
与PluginProcess()
函数的接口,因此,PluginBase
接口的任何其他用户都可以调用它而无需关心其实现。
如果你需要另一个接口与另一个方法 - 以同样的方式做。
class PluginPlumbing {
public:
virtual void PlumbingFunction() = 0;
};
隐藏DLL实现中的实现:
class PluginPlumbingImpl : public PluginPlumbing {
public:
void PlumbingFunction() override {
// do the stuff
}
}
如果需要其他参数 - 也将其作为抽象接口类或POD结构传递。你还应该为你的插件函数做一些声明,它将为你的接口实现创建精确的实例(插件的用户应该可以访问它)。
总结一下,你应该有类似的东西:
// myplugininterface.h
// this header will be exposed to plugin implementors and
// plugin consumers
class IMyPluginClass1 {
public:
virtual void func1() = 0;
virtual void func2() = 0;
}
// another interface, ties together other functionality
class IMyPluginClass2 {
public:
virtual void func1() = 0;
// you can even pass around your interface classes
virtual void doSomethingWithAnotherObject(IMyPluginClass1 *obj) = 0;
// or use "factory" methods to create objects
virtual IMyPluginClass1 *createObject() = 0;
}
// this is functions implemented by a plugins, they should create
// instances for your plugin objects
// you could do them as a static methods of your classes if you don't
// plan to expose that as C compatible plugins
IMyPluginClass1 *createObject1();
IMyPluginClass2 *createObject2();
// mycoolplugin.cpp
// specific implementation of your plugin, you or someone else
// compile this to plugin DLL
#include "myplugininterface.h"
class IMyPluginClass1Impl : public IMyPluginClass1 {
public:
IMyPluginClass1Impl() :
myMyValue(100500)
{}
void func1() override {
// implement
}
void func2() override {
// implement
}
private:
// you can have any private or even public members in your implementation
int mMyValue;
};
class IMyPluginClass2Impl : public IMyPluginClass2 {
public:
void func1() override {
// implement
}
void doSomethingWithAnotherObject(IMyPluginClass1 *obj) override {
// implement
// but don't assume you can cast IMyPluginClass1 to
// something specific, because it might be not yours implementation
// it depends on how carefully you design your interfaces and
// explain to plugin writers what is allowed and what is not
}
IMyPluginClass1 *createObject() {
// be careful with that, in that case you MUST declare
// virtual destructor as a part of your interface class
return new IMyPluginClass1Impl();
}
};
IMyPluginClass1 *createObject1() {
return new IMyPluginClass1Impl();
}
IMyPluginClass2 *createObject2() {
return new IMyPluginClass2Impl();
}
您插件的用户只能通过加入myplugininterface.h
和来使用它
获取create
函数的地址(这取决于平台)。
请记住,如果您返回new
创建的实例并允许
您的插件的用户是delete
这样创建的对象 - 您必须这样做
为您的接口类声明虚拟析构函数。
这是一种通用方法。当你有层次结构时,它有一些陷阱 你的插件对象,你不能分享你的摘要的常见实现 没有付出额外努力的课程(假设你不想拥有copypasta)