【问题标题】:Calling function from (Qt) plugin fails从(Qt)插件调用函数失败
【发布时间】:2014-01-28 11:33:57
【问题描述】:

我想编写一个包含几个插件的应用程序。我的想法是插件本身始终只是一个工厂,然后可以创建所需的对象。

因此,我使用名为 create 的纯虚拟方法为名为 AbstractFactoryPlugin 的插件工厂创建了一个接口。因为我想要几个不同的插件(工厂)具有相同的接口,所以我不能将 Q_DECLARE_INTERFACE 宏放在 AbstractFactoryPlugin 头文件中。

因此,对于一个示例插件,我创建了一个继承自 AbstractFactoryPlugin 的接口,称为 IMyObjectFactoryPlugin,并使用 DECLARE 宏声明了此接口。然后 MyObjectFactoryPlugin 继承自 QObject 和 IMyObjectFactoryPlugin。

但是当我加载插件并调用create函数时,MyObjectFactoryPlugin的create函数似乎从来没有被调用过。我做错了什么?

提前感谢。

源码:

#ifndef ABSTRACTPLUGINFACTORY_H
#define ABSTRACTPLUGINFACTORY_H

#include "IAnObject.h"

class AbstractFactoryPlugin
{
    public:
        virtual ~AbstractFactoryPlugin() {}

        virtual IAnObject *create(QObject *parent) = 0;
};

#endif // ABSTRACTPLUGINFACTORY_H

#ifndef IMYOBJECTFACTORYPLUGIN_H
#define IMYOBJECTFACTORYPLUGIN_H

#include "AbstractFactoryPlugin.h"

#include <QtPlugin>

class IMyObjectFactoryPlugin : public AbstractFactoryPlugin
{
    public:
        virtual ~IMyObjectFactoryPlugin() {}
};


QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(IMyObjectFactoryPlugin,
                    "org.MyObjectFactoryPlugin");
QT_END_NAMESPACE

#endif // IMYOBJECTFACTORYPLUGIN_H

#ifndef MYOBJECTPLUGIN_H
#define MYOBJECTPLUGIN_H

#include <QtPlugin>
#include "IMyObjectFactoryPlugin.h"
#include "AbstractFactoryPlugin.h"

class MyObjectFactoryPlugin : public QObject, IMyObjectFactoryPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.MyObjectFactoryPlugin" )
    Q_INTERFACES(IMyObjectFactoryPlugin)

    public:
        MyObjectFactoryPlugin(QObject *parent = 0);
        IAnObject *create(QObject *parent);
};

#endif // MYOBJECTPLUGIN_H

#include "MyObject.h"
#include "MyObjectFactoryPlugin.h"
#include <QDebug>

MyObjectFactoryPlugin::MyObjectFactoryPlugin(QObject *parent) :
    QObject(parent)
{

}

IAnObject *MyObjectFactoryPlugin::create(QObject *parent)
{
    qDebug() << Q_FUNC_INFO << "was called";
    return new MyObject();
}

#ifndef IANOBJECT_H
#define IANOBJECT_H

class IAnObject
{
    public:
        IAnObject() {isInitialized = false;}
        virtual ~IAnObject() {}

        virtual bool initialize() = 0;

    protected:
        bool isInitialized;
};

#endif // IANOBJECT_H

#include "IAnObject.h"

#ifndef MYOBJECT_H
#define MYOBJECT_H

class MyObject : public IAnObject
{
    public:
        MyObject();
        bool initialize();
};

#endif // MYOBJECT_H

#include "MyObject.h"

MyObject::MyObject()
{
}


bool MyObject::initialize()
{
    return true;
}

#include <QCoreApplication>
#include <QDir>
#include <QPluginLoader>
#include <QDebug>

#include <E:/QtProjects/_test_PlugIn/MyPlugin/AbstractFactoryPlugin.h>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/IAnObject.h>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/IMyObjectFactoryPlugin.h>

IAnObject *loadPlugin()
{
    QDir dir(QCoreApplication::applicationDirPath());

    qDebug() << dir;

    foreach(QString fileName, dir.entryList(QDir::Files))
    {
        QPluginLoader pluginLoader(dir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();

        qDebug() << fileName;

        if(plugin)
        {
            qDebug() << "##### Plugin load ok #####";

            AbstractFactoryPlugin *abstractFactoryPlugin = reinterpret_cast<AbstractFactoryPlugin *>(plugin);

            return abstractFactoryPlugin->create(NULL);
        }
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "loadPlugin:" << loadPlugin();

    return a.exec();
}

【问题讨论】:

  • 您是否尝试过 dynamic_cast 而不是 reinterpret_cast?
  • 使用 dynamic_cast 应用程序崩溃。使用调试器单步执行会导致异常:---------------------------- Exception Triggered ----------- ----------------

    下级停止,因为它触发了一个异常。

    在线程 0 中停止:异常在 0xad1aad,代码:0xc0000005:读取访问冲突在: 0x0,标志=0x0(第一次机会)。 - - - - - - - - - - - - - - 好的 - - - - - - - - - - - -----

标签: c++ qt plugins


【解决方案1】:

任何 Qt5 插件都必须继承自 QObject,如果您希望基类独立于 QObject,则必须创建一个继承 AbstractFactoryPlugin 和 QObject 的中间类(我们称之为 AbstractMyObjectFactoryPlugin)。

#ifndef ABSTRACTMYOBJECTFACTORYPLUGIN_H
#define ABSTRACTMYOBJECTFACTORYPLUGIN_H

#include "AbstractFactoryPlugin.h"

class AbstractMyObjectFactoryPlugin : public QObject, public AbstractFactoryPlugin
{
  Q_OBJECT
public:
  AbstractMyObjectFactoryPlugin(QObject *parent = 0) : QObject(parent) { }
  virtual ~AbstractMyObjectFactoryPlugin() { }
};

Q_DECLARE_INTERFACE(AbstractMyObjectFactoryPlugin,
                    "org.AbstractFactoryPlugin");

#endif // ABSTRACTMYOBJECTFACTORYPLUGIN_H

要创建插件,您必须从此类继承并覆盖 create() 方法:

class MyObjectFactoryPlugin : public AbstractMyObjectFactoryPlugin
{
  Q_OBJECT
  Q_INTERFACES(AbstractMyObjectFactoryPlugin)
  Q_PLUGIN_METADATA(IID "org.MyObjectFactoryPlugin" FILE "MyObjectFactoryPlugin.json")
public:
  MyObjectFactoryPlugin(QObject* parent = 0) : AbstractMyObjectFactoryPlugin(parent) { }
  virtual IAnObject *create(QObject *parent);
  virtual ~MyObjectFactoryPlugin() { }
};

要将加载的插件(一个 QObject)安全地转换为 AbstractFactoryPlugin,您必须先将其转换为中间类。

AbstractFactoryPlugin * objectFactoryPlugin = qobject_cast< AbstractMyObjectFactoryPlugin * >(plugin);

隐式赋值会将其转换为正确的基类。

注意:如果你有其他继承树,你必须先检查转换是否成功。

【讨论】:

  • 我忘了说我使用的是 Qt5。这就是我不使用 Q_EXPORT_PLUGIN2 的原因,因为它已被弃用,而是使用 Q_PLUGIN_METADATA 宏。按照您的建议编辑我的代码有效。但是,如果我想从 AbstractFactoryPlugin 派生更多插件,因为 Q_DECLARE_INTERFACE 宏的标识符相同,将 Q_DECLARE_INTERFACE 放入 AbstractFactoryPlugin 不是问题吗?这就是我试图避免这种情况的原因,正如我在第一篇文章中所写的那样:“因为我想拥有几个具有相同界面的不同插件(工厂),所以我不能放置 Q_DE……”
  • 我更新了我的答案,这对我有用;虽然我不清楚这是否是你所追求的。
  • 除了一件事外它可以工作。我从 AbstractFactoryPlugin 派生了另一个插件(例如 AbstractOtherObjectFactoryPlugin)。如果加载了这个插件,这个 cast 可以工作,尽管它应该返回 0:qobject_cast(plugin)。将 Q_DECLARE_INTERFACE 的标识符从 org.AbstractFactoryPlugin 更改为 org. AbstractMyObjectFactoryPlugin 用于 AbstractMyObjectFactoryPlugin 和 org. AbstractOtherObjectFactoryPlugin 的 AbstractOtherObjectFactoryPlugin 似乎工作得更好。让每个接口都有自己的标识符不是更好吗?还是我这样做错了?
  • 你所有的插件都应该直接继承自AbstractMyObjectFactoryPlugin,这实际上只是一个包裹AbstractFactoryPluginQObject,如果你想直接从AbstractFactoryPlugin继承你可以,但只能在里面相同的应用程序(从 AbstractFactoryPlugin 继承的插件根本不应该工作,但在您的测试中这样做,因为它们具有相同的签名)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多