我想制作一个带有插件的应用程序,它也可以有插件(主应用程序不需要知道)。原因是我想为一些代码项目制作一个通用的IDE,然后我制作了一个图像处理插件。然后我希望图像处理程序插件有一些自己的过滤器插件,主应用程序不需要知道。这可能吗?
以下是我得到的自我:
我想制作一个有一些接口的主IDE。
class IDocumentFactory
{
public:
virtual ~IDocumentFactory() {}
//virtual QStringList documents() const = 0;
virtual QVector<FileOpenEntries> name_filters() const = 0;
virtual QWidget* open_document( QWidget* parent,
const QStringList &filepaths,
const QString &name_filter_key) const = 0;
};
Q_DECLARE_INTERFACE(IDocumentFactory, "S-DAIDE.IDocumentFactory/1.0")
class IDeclarePlugins
{
public:
virtual ~IDeclarePlugins() {}
virtual QStringList plugins() const = 0;
virtual void load_plugings(QObject * plugins) = 0;
};
Q_DECLARE_INTERFACE(IDeclarePlugins, "S-DAIDE.IDeclarePlugins/1.0")
现在我想在我的插件中定义一个其他插件可以实现的接口。
class MyPlugin : public QObject, IDeclarePlugins
{
Q_OBJECT
Q_INTERFACES(IDeclarePlugins)
...
QStringList ImagePlugin::plugins() const
{
return QStringList() << "S-DAIDE.ImagePlugin.IOverlay/1.0";
}
}
在我的主要应用加载插件。
foreach (QString fileName, m_plugins_dir.entryList(QDir::Files)) {
QPluginLoader loader(m_plugins_dir.absoluteFilePath(fileName));
QObject *plugin = loader.instance();
}
有没有一种方法可以检查插件是否实现了基于Q_DECLARE_INTERFACE
使用的字符串的接口。这样我就可以让插件加载它通过virtual QStringList plugins() const = 0;
声明的所有其他插件
根据设计,您应该使用qobject_cast
来接口类,但不能使用那些ids
。
您仍然可以创建一个函数QString id()
,该函数将为每个插件返回id
,您可以在加载程序代码中检查该函数的结果。
你可以检查一下,如果你的插件已经给出了id
,原则上,你可以在Q_DECLARE_INTERFACE
宏防御中找到它的方法。
bool isIdMatch = const_cast<QObject *>(object)->qt_metacast(IId) != 0;
但是qt_metacast
没有文档,所以我不建议您使用这种方法。
如果你想摆脱重复写id两次的情况,你可以使用宏,Qt的框架非常喜欢它自己:
#define DECLARE_ID(__iid)
virtual QString id() const {return iid_private();}
static const char* const iid_private() {return __iid;}
#define GET_ID(IFace) IFace::iid_private()
class IFace
{
public:
DECLARE_ID("Iface")
};
Q_DECLARE_INTERFACE(IFace, GET_ID(IFace))
class IFace2: public IFace
{
public:
DECLARE_ID("Iface2")
};
Q_DECLARE_INTERFACE(IFace2,GET_ID(IFace2))
int main(int c, char**v)
{
IFace* f = new IFace2();
qDebug() << f->id() << f->iid_private();
qDebug() << GET_ID(IFace) <<GET_ID(IFace2);
return 0;//a.exec();
}
研究输出并注意,您应该使用id()
函数而不是iid_private