Question

I have an application which is basically a plugin manager. This application should be able to deal with an arbitrary numbers of plugins which have the same interface but can behave differently.

To achieve this, the plugins have this class hierarchy:

enter image description here

In this minimal example each plugin has just two methods: getName which returns a hardcoded string and geId which returns a string stored in a text file which will be compiled into a resource file of each plugin.

The thing is: each plugin returns its hardcoded name. But the returned Id is the Id of the first plugin in both cases (see output).

Why is that? This is the code and the application output:

Application output

############# Plugin load ok #############
"Plugin01"
"p01"

############# Plugin load ok #############
"Plugin02"
"p01"
############# ready #############   

main.cpp

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QDir dir(QCoreApplication::applicationDirPath());

    foreach(QString fileName, dir.entryList(QDir::Files))
    {
        QPluginLoader pluginLoader(dir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if(plugin)
        {
            qDebug() << endl << "############# Plugin load ok #############";
            if(dynamic_cast<IPlugin* >(plugin))
            {
                qDebug() << dynamic_cast<IPlugin* >(plugin)->getName();
                qDebug() << dynamic_cast<IPlugin* >(plugin)->getId();
            }
        }
    }

    qDebug() << "############# ready #############";
    return a.exec();
}

IPlugin.h

class IPlugin : public QObject
{
    Q_OBJECT

    public:
        IPlugin(QObject *parent = 0) : QObject(parent) {}
        virtual ~IPlugin() {}
        virtual QString getId() = 0;
        virtual QString getName() = 0;
};

IPlugin01.h

class IPlugin01 : public IPlugin
{
    public:
        IPlugin01(QObject *parent) : IPlugin(parent) {}
        virtual ~IPlugin01() {}
};

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(IPlugin01,
                    "Plugin01/0.1");
QT_END_NAMESPACE

Plugin01.h

class Plugin01 : public IPlugin01
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "Plugin01/0.1")
    Q_INTERFACES(IPlugin01)

    public:
        Plugin01(QObject *parent = 0);
        virtual QString getId();
        virtual QString getName();
};

Plugin01.cpp

Plugin01::Plugin01(QObject *parent) :
    IPlugin01(parent)
{

}

QString Plugin01::getId()
{
    QFile file(":/id.txt");

    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return file.readAll();
    }

    return "";
}

QString Plugin01::getName()
{
    return "Plugin01";
}

id.txt of Plugin01's resource file

p01 

IPlugin02.h

class IPlugin02 : public IPlugin
{
    public:
        IPlugin02(QObject *parent) : IPlugin(parent) {}
        virtual ~IPlugin02() {}
};

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(IPlugin02,
                    "Plugin02/0.1");
QT_END_NAMESPACE

Plugin02.h

class Plugin02 : public IPlugin02
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "Plugin02/0.1")
    Q_INTERFACES(IPlugin02)

    public:
        Plugin02(QObject *parent = 0);
        virtual QString getId();
        virtual QString getName();
};

Plugin02.cpp

Plugin02::Plugin02(QObject *parent) :
    IPlugin02(parent)
{

}

QString Plugin02::getId()
{
    QFile file(":/id.txt");

    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return file.readAll();
    }

    return "";
}


QString Plugin02::getName()
{
    return "Plugin02";
}

id.txt of Plugin02's resource file

p02 
Was it helpful?

Solution

Resource path are "global", so, :/id.txt is incorrect. You should design your resource structure in other way. Or you should load resources manually.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top