Russian Qt Forum

Qt => Вопросы новичков => Тема начата: devnikor от Январь 25, 2014, 19:41



Название: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 19:41
Здравствуйте. Написал плагин и пытаюсь его загрузить в рантайме с помощью QPluginLoader, но метод instance() возвращает 0. Не подскажете, почему?
Вот интерфейс плагина:
Код:
#include <QtPlugin>
#include <QWidget>

class PluginInterface : public QWidget {

public:
    virtual ~PluginInterface() { }
    virtual void start() = 0;
    virtual void settings() = 0;
    //signal
    virtual void notificationIsReady(const QString& title, const QString& description,
                                 const QString& image) = 0;

};

Q_DECLARE_INTERFACE(PluginInterface, "com.devlab.Notifier.PluginInterface")

Сам плагин:
Код:
#include <PluginInterface.hpp>
#include <QTimer>

class TestPlugin : public PluginInterface {
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "com.devlab.Notifier.PluginInterface")
    Q_INTERFACES(PluginInterface)

private:
    QTimer* timer;

public:
    TestPlugin();
    virtual ~TestPlugin();
    virtual void start();
    virtual void settings();

signals:
    void notificationIsReady(const QString& title, const QString& description,
                             const QString& image);
private slots:
    void timerSlot();
};

TestPlugin::TestPlugin() {
    timer = new QTimer(this);
    timer->setInterval(1000);
}

TestPlugin::~TestPlugin() {
    delete timer;
}

void TestPlugin::start() {
    connect(timer, &QTimer::timeout, this, &TestPlugin::timerSlot);
    timer->start();
}

void TestPlugin::settings() { }

void TestPlugin::timerSlot() {
    emit notificationIsReady("Test", "It's works", "");
}

Пытаюсь сделать так, чтобы можно было соединить сигнал плагина со слотом своего класса.
Как загружаю:
Код:
QString path("C:/Users/devnikor/Documents/Projects/Notifier/Notifier/plugins/TestPlugin.dll");
    QPluginLoader loader(path);
    QObject* plugin = loader.instance();
    PluginInterface* testPlugin = qobject_cast<PluginInterface*>(plugin);
    connect(testPlugin, SIGNAL(notificationIsReady(QString, QString, QString)),
            this, SLOT(testSlot(QString, QString, QString)));


Название: Re: Не могу загрузить плагин
Отправлено: gil9red от Январь 25, 2014, 19:54
Нужно добавить Q_EXPORT_PLUGIN2 или Q_EXPORT_PLUGIN :)

Пример создания плагина:
http://doc.crossplatform.ru/qt/4.4.3/designer-customwidgetplugin-customwidgetplugin-cpp.html


Название: Re: Не могу загрузить плагин
Отправлено: Old от Январь 25, 2014, 20:02
Нужно добавить Q_EXPORT_PLUGIN2 или Q_EXPORT_PLUGIN
Судя по его коду у него Qt5.

Здравствуйте. Написал плагин и пытаюсь его загрузить в рантайме с помощью QPluginLoader, но метод instance() возвращает 0. Не подскажете, почему?
Посмотрите, что за ошибка будет возвращатся после instance. QPluginLoader::errorString()


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 20:06
gil9red, пишу на Qt5, там вроде надо Q_PLUGIN_METADATA

Old, Unknown error  :)


Название: Re: Не могу загрузить плагин
Отправлено: Johnik от Январь 25, 2014, 20:36
Для начала попробуйте класс интерфейса без наследования от QWidget
gil9red, пишу на Qt5, там вроде надо Q_PLUGIN_METADATA
Именно так.

Old, Unknown error  :)
было подобное на Qt4, проблемы искал отладчиком. В итоге оказалось что не все зависимые либы были найдены


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 20:49
Johnik, тогда в плагине наследовать и интерфейс и QWidget? Мне просто нужно, что бы сигналы работали


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 20:54
Без наследования от QWidget и макроса Q_OBJECT QPluginLoader::errorString() выдает:
Код:
"Plugin verification data mismatch in 'C:/Users/devnikor/Documents/Projects/Notifier/Notifier/plugins/TestPlugin.dll'" 


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 20:56
На всякий случай приложу код в pro файле
Код:
QT += core widgets

TEMPLATE = lib
 CONFIG += plugin
INCLUDEPATH += ../Notifier/Notifier

HEADERS += \
    testplugin.hpp

SOURCES += \
    testplugin.cpp

DESTDIR = ../Notifier/Notifier/plugins


Название: Re: Не могу загрузить плагин
Отправлено: Old от Январь 25, 2014, 21:01
Вы и из TestPlugin убрали наследование от QWidget и Q_OBJECT?


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 21:05
Old, да


Название: Re: Не могу загрузить плагин
Отправлено: Old от Январь 25, 2014, 21:10
В TestPlugin нужно добавить двойное наследование от QWidget и интерфейс, и добавить Q_OBJECT.


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 21:22
Old, сделал, теперь флаг did_load находится в true
но теперь ошибка с connect:
Код:
C:\Users\devnikor\Documents\Projects\Notifier\Notifier\notificationcenter.cpp:35: ошибка: no matching function for call to 'NotificationCenter::connect(PluginInterface*&, const char*, NotificationCenter* const, const char*)'
             this, SLOT(testSlot(const QString&,const QString&,const QString&)));
                                                                               ^

вызов:
Код:
connect(testPlugin, SIGNAL(notificationIsReady(const QString&,const QString&,const QString&)),
            this, SLOT(testSlot(const QString&,const QString&,const QString&)));


Название: Re: Не могу загрузить плагин
Отправлено: Johnik от Январь 25, 2014, 21:41
забудьте пока о connect. Плагин грузится?

по поводу сигналов в плагине, вот тут говорится один из вариантов как это сделать:
http://www.prog.org.ru/topic_5403_0.html


Название: Re: Не могу загрузить плагин
Отправлено: Old от Январь 25, 2014, 22:01
но теперь ошибка с connect:
Да, сейчас интерфейс не является наследником QObject и не может посылать сигналы, а connect ждет первым параметром указатель на наследника QObject.

Вам нужно разделить ваш код на две сущности:
- объект плагина
- объект работник (который создается объектом плагина).

Вот первый будет не наследник QObject и не сможет использовать сигналы, но он сможет создавать после своей загрузки объект-работник, который уже будет наследником QObject и сможет сигналить. Примеры этого можно посмотреть по ссылке, которую дал Johnik выше.


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 25, 2014, 22:05
Спасибо вам всем большое, целый день бился с этой проблемой.


Название: Re: Не могу загрузить плагин
Отправлено: devnikor от Январь 26, 2014, 13:18
Сигналы тоже заработали. На всякий случай оставлю тут решение:
В интерфейсе плагина добавил такой чистый виртуальный метод:
Код:
virtual QObject* getObject() = 0;
В самом классе плагина наследуюсь от QWidget и интерфейса плагина, дальше переопределяю метод getObject():
Код:
QObject* TestPlugin::getObject() {
    return qobject_cast<QObject*>(this);
}

И переопределяю метод как сигнал:
Код:
signals:
    void notificationIsReady();

В главной программе соединяю этот сигнал со своим слотом:
Код:
connect(testPlugin->getObject(), SIGNAL(notificationIsReady()), this, SLOT(testSlot()));