avb
avb

Reputation: 1751

Calling function from (Qt) plugin fails

I want to write an application which consists of several plugins. My idea is that the plugin itself is always just a factory which then can create the required object.

So I created an Interface for the pluginfactory called AbstractFactoryPlugin with a pure virtual method called create. Because of the fact that I want to have several different plugins (factories) with the same interface I can’t put the Q_DECLARE_INTERFACE macro in the AbstractFactoryPlugin header file.

So for a sample plugin I created an Interface which inherits from AbstractFactoryPlugin called IMyObjectFactoryPlugin and declared this interface with the DECLARE macro. Further the MyObjectFactoryPlugin then inherits from QObject and IMyObjectFactoryPlugin.

But when I load the plugin and call the create function, the create function of MyObjectFactoryPlugin seems to be never called. What am I doing wrong?

Many thanx in advance.

Sourcecode:

#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();
}

Upvotes: 1

Views: 795

Answers (1)

voodooattack
voodooattack

Reputation: 1176

Any Qt5 plugin must inherit from QObject, if you want your base class to be independent from QObject you'll have to create an intermediary class that inherits both AbstractFactoryPlugin and QObject (let's call it 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

To create a plugin, you'll have to inherit from this class and override the create() method:

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() { }
};

To cast the loaded plugin (a QObject) to AbstractFactoryPlugin safetly, you'll have to cast it to the intermediary class first.

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

The implicit assignment will cast it to the right base class.

Note: You'll have to check if the cast is successful first if you have other inheritance trees.

Upvotes: 1

Related Questions