QPluginLoader and shared resources



  • I am trying to create a plugin-based application with a plugin manager which will load dynamic plugins. Everything is OK, I create successfuly plugins and they work just fine, I can create signals and slots and attach them to the main application on plugin instantination, but this is the only way to communicate between the plugin and the app. I tried various methods to pass the main app object as a parameter for the plugin or alike, including setting of a qApp property, with the idea to be able to call methods or to read values straight from the main app.

    What I want to do is to have a single stream opened and work straight on it from the different plugins, instead of passing everything as signals and slots. What I am after is better control from the plugins themself. Does anyone have any idea on how I can achieve something similar?

    Here is what I do. This is in the class which is being called in main:
    @
    qDebug() << "Init done.\nLoading plugins.";

        QDir pluginsDir = QDir(qApp->applicationDirPath());
        pluginsDir.cdUp();
        pluginsDir.cd("plugins");
     
        foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
            QPluginLoader *loader = new QPluginLoader(pluginsDir.absoluteFilePath(fileName),this);
            QObject *plugin = loader->instance();
            if (plugin) {
                connect(plugin,SIGNAL(msg(QString,QString,QString)),this,SLOT(msg(QString,QString,QString)));
                pluginInterface *pl = qobject_cast(plugin);
                pl->init(this);
                plugindata plug;
                plug.object = plugin;
                plug.name = pl->Name();
                plug.version = pl->Version();
     
                plugins.insert(plug.name,plug);
            } else {
                qDebug() << loader->errorString();
            }
        }
    

    @

    plugindata is a simple struct which collects the information about the plugins, but right now there is nothing being done with it.

    @
    struct plugindata {
    QString name;
    QString version;
    QObject *object;
    };
    @

    plugins is a QMap for saving plugin data (name as key, plugin object as value)

    @
    QMap<QString, plugindata> plugins;
    @

    The plugin interface:
    @
    class kernel;

    class pluginInterface {
    public:
        /**
          * Returns the name of the Plugin
          */
        virtual QString Name() = 0;
     
        virtual QString Version() = 0;
     
        virtual void event(QStringList leftParams, QString rightSide) = 0;
     
        virtual void init(kernel *obj) = 0;
     
    };
    

    @

    This, with the relevant Q_DECLARE_INTERFACE for interface declaration.

    In the cpp file of the plugin, I have this:

    @
    void Numerics::init(kernel *p)
    {
    this->p = p;
    }

    void Numerics::event(QStringList leftParams, QString rightSide)
    {
        qDebug() << "msg from plugin via signal";
        emit msg("test","tralala","p");
     
        qDebug() << "msg from plugin parent object";
        p->msg("test","test","p");
    }
    

    @

    where "p" is declared in the header

    emiting a signal works OK.

    The app shows error on this line:

    @
    p->msg(“test”,“test”,“p”);
    @

    and the error is as follows:

    @
    msg from plugin parent object
    <absolute path to the debug dir>: symbol lookup error: <absolute path to plugin dir>/libnumerics.so: undefined symbol: ZN6kernel3msgE7QStringS0_S0
    @

    if I leave it with the signal and the slot only, it works just fine (when I comment out the "p->msg" line).



  • Anyone? :(



  • Okay, I tried to keep it going, MySQL connection is not a problem for the plugins (since the driver and all the database details are needed only once application wide), it will work with signals and slots, but I still need to expose the application object to he plugins somehow, so they can control the behaviour of the application in one way or another. My idea is to give myself the oportunity to extend the applications I make in a way which would allow me to edit the plugins to fix bugs or add extra functionallity without modifying the core.

    In that matter, I tried to unload a plugin using the unload() method of the QPluginLoader, but it doesn't seem to unload it properly. Can someone give me working example on how to unload a plugin, so it uses less memory or can be reloaded (say with updated version, without the need to restart the whole application)?



  • Can anyone help me please?

    I am looking for a way to give my plugins more control on how the application runs, I want to be able to control my application via plugins, I want to be able to extend my application with adding more plugins.



  • You should take a look at the source code of the Qt Creator. It's also fully based on plugins.



  • Yeah, even though I know that, I haven't thought about it. It will take a while to get the information from there, thought that the forums would be faster to get response from ;-)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.