Seite 1 von 1

QPluginLoader will Plugin nicht laden

Verfasst: 26. November 2008 19:03
von BeS
Hallo,

ich versuche hier verzweifelt ein Plugin in meine Anwendung zu laden, aber es klappt nicht. Hier mal der Code:

Das Interface für das Plugin ist so definiert:

Code: Alles auswählen

#ifndef INTERFACE_H
#define INTERFACE_H

#include <QtPlugin>

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

    virtual QString pluginName();
};

Q_DECLARE_INTERFACE(PluginInterface, "cops.demo.PluginInterface/1.0")

#endif
das Plugin selber sieht dann so aus:

Code: Alles auswählen

#ifndef MYPLUGIN_H
#define MYPLUGIN_H

#include <QString>

#include "myPlugin.h"
#include "../pluginInterface.h"


class MyPlugin : public QObject, public PluginInterface
{
    
    Q_OBJECT
    Q_INTERFACES(PluginInterface)
            
public:
    QString pluginName();
  
};

#endif
und so:

Code: Alles auswählen

#include <QtGui>
#include <iostream>

#include "myPlugin.h"

QString MyPlugin::pluginName()
{
    return "My Plugin Name";
}

Q_EXPORT_PLUGIN2(myplugin, MyPlugin)
Das Plugin kann ich Übersetzen und es wird dann im plugin-Verzeichnis unter dem Namen libmyPlugin.so abgelegt.

Jetzt versuche ich es aus meiner Anwendung zu laden:

Code: Alles auswählen

void MainWindow::loadPlugins()
{
    QDir pluginDir(QApplication::applicationDirPath());
    
    if (!pluginDir.cd("plugins"))
        return;

    foreach (QString fileName, pluginDir.entryList(QDir::Files)) {
        std::cout << qPrintable(fileName)  << "\n";
        QPluginLoader loader(pluginDir.absoluteFilePath(fileName));
        if (PluginInterface *interface = qobject_cast<PluginInterface *>(loader.instance())) {
            interfaces.append(interface);
            std::cout << qPrintable(interface->pluginName()) << "loaded \n";
        } else {
            std::cout << "not loaded!\n";
        }
    }
}
Das Plugin wird gefunden "std::cout << qPrintable(fileName) << "\n";" gibt den Dateinamen des Plugins aus. Allerdings wird die IF Anweisung nie "true" und ich lande immer im else-Zweig.

Hat ihr eine Idee was hier nicht stimmt?

Danke!

Verfasst: 26. November 2008 19:51
von solarix
Wie wär's wenn man die verfügbaren Qt-Boardmittel nutzt?
1. hast du irgendwelche Ausgaben in der Konsole
2. was liefert loader.isLoaded()
3. was liefert loader.errorString()
4. liefert loader.instance() NULL oder einen Pointer (schlägt der Cast fehl?)

Etwas OT aber "if (PluginInterface *interface =" ist echt hässlich..

Etwas weniger OT:
Die Referenz "QString PluginInterface::pluginName()" fehlt noch.. also besser abstrakt machen: "QString pluginName() = 0;"

Verfasst: 2. Dezember 2008 18:21
von Antis_81
Hi,

also erstmal musst du die Methoden im Interface als pure virtual deklarieren. Das geht einfach: virtual methodeXY() =0;

Wurde das Problem eigentlich mittlerweile gelöst? Bei mir will es nämlich auch partout nicht laden. Möchte nur nicht den ganzen Code anhängen :D

[gelöst]

Verfasst: 3. Dezember 2008 16:14
von Antis_81
Hi,
vielleicht hilft's ja dem ein oder anderen. Ich habe eine Plugin.dll und zum Test ein Pluginloader.exe nach Dokumentation und Beispielen in Qt erstellt.

Sprich ...
... Interface mit NUR pure virtual Funktionen und Q_DECLARE_INTERFACE
... Plugin Klasse von Interface und QObject abgeleitet
... In Plugin Implementierung Q_EXPORT_PLUGIN2 eingebaut

Und zum Schluss eine Exe mit einem QPluginLoader erzeugt.

Problem:
Beides baut, aber das Plugin wird nicht geladen (QPluginLoader::instance() liefert NULL).

Lösung - Man höre und staune:

Qt 4.3.3 hat einen Bug im QPluginLoader, so dass man diesen wahrscheinlich gar nicht verwenden kann (hab's nicht mehr getestet). Habe ohne meinen Code zu ändern Qt 4.4.3 parallel installiert, dass ganze erneut kompiliert und - oh Wunder - es geht!

Habe dann mal die Sourcen des PluginLoaders verglichen und tatsächlich - sie sind an wesentlichen Stellen unterschiedlich (Wen's interessiert, die Zuweisung des Pointers 'd' ist das Problem).

Hoffe, dass verkürzt die Fehlersuche bei Leidensgenossen - Also bei mir geht's jetzt jedenfalls :P