Экземпляр QPluginLoader всегда возвращает null

94
8

Я занимаюсь разработкой приложения Qt. Хотя я запрограммировал много вещей GUI раньше, и сама инфраструктура не представляет проблемы, я ни разу не программировал (за пределами приложений С#.NET), которая имеет возможность загружать плагины. Проект, который я пытаюсь создать, имеет плагины как неотъемлемую часть его, и я думал, что структура Qt выглядела неплохо для этого, потому что она была почти повсеместно кросс-платформенной и, похоже, была очень приятной системой для плагинов.

Моя проблема заключается в следующем: я не могу заставить QPluginLoader.instance() возвращать что-либо, кроме нулевого значения.

Из моих чтений это происходит потому, что он не видит плагина. Я думаю, что я, вероятно, забываю что-то сделать, но я могу найти очень мало документации по написанию плагинов (есть примеры, но они не невероятно детализированы). Есть много примеров загрузки плагинов, и я думаю, что я делаю это правильно, но я действительно не нашел пример создания плагина.

Это то, что я сделал:

Используя Qt-Creator, я создал два проекта: оконное приложение, чтобы притворяться, что это приложение для моего плагина и проект общей библиотеки, чтобы притворяться плагином

В моем оконном приложении у меня есть файл заголовка следующим образом:

#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H

#include <QtPlugin>

class QStringList;

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

virtual QStringList messages() const = 0;
};

Q_DECLARE_INTERFACE(PluginInterface,
"com.kevincuzner.LearningPlugins.PluginInterface/1.0")

#endif // PLUGININTERFACE_H

В приложении моей общей библиотеки я создал класс ATestPlugin (и это также значение TARGET проекта):

#ifndef ATESTPLUGIN_H
#define ATESTPLUGIN_H

#include "ATestPlugin_global.h"
#include "../LearningPlugins/PluginInterface.h"

#include <QStringList>

class ATESTPLUGINSHARED_EXPORT ATestPlugin : public PluginInterface, public QObject
{

Q_OBJECT
Q_INTERFACES(PluginInterface)

public:
ATestPlugin();

virtual QStringList messages() const
{
//this part is actually defined in the .cpp file, but I don't feel like pasting that here
QStringList ret;
ret << "foo" << "bar" << "noms" << "Hello";

return ret;
}
};

#endif // ATESTPLUGIN_H

В конце файла ATestPlugin.cpp я разместил Q_EXPORT_PLUGIN2(ATestPlugin, ATestPlugin)

Затем в основном файле main.cpp в основном методе я делаю следующее (& w указывает на главное окно):

QString text = QFileDialog::getOpenFileName(&w, "Get a file");
QPluginLoader loader(text);
QObject* plugin = loader.instance();
if (plugin)
{
QMessageBox msgBox;
msgBox.setText(text);
msgBox.exec();
}

Когда я запускаю программу и выбираю libATestPlugin.so из каталога сборки моего проекта библиотеки в появившемся диалоговом окне файла, я не вижу окна сообщений, что означает, что * плагин равен NULL. Раньше у меня всегда появлялся ящик сообщений и показывал имя выбранного файла, поэтому я знаю, что эта часть работает.

У кого-нибудь есть идеи относительно того, что мне нужно сделать, чтобы сделать мой плагин видимым для QPluginLoader?

спросил(а) 2012-10-06T22:41:00+04:00 8 лет, 3 месяца назад
1
Решение
119

После дальнейших экспериментов мне удалось загрузить плагин. Я чувствую себя застенчивым, говоря это, но это был классический случай RTFM.

Учебник по echo-плагину (который я не нашел до тех пор, пока я не опубликовал вопрос) не вносил некоторые изменения, которые должны были быть внесены в.pro файл в библиотеке, чтобы заставить его правильно объявить плагин:

Строка TARGET = ATestPlugin должна была быть изменена на TARGET = $$qtLibraryTarget(ATestPlugin). После внесения этого изменения, появилось мое сообщение в приведенной выше программе, а позже, когда я запустил qobject_cast< PluginInterface* >(plugin) а затем попросил PluginInterface->messages() я получил список, который был реализован в отдельном классе.

Кроме того, я изменил порядок наследования, чтобы сначала поставить QObject, и поскольку он работает таким образом, я, вероятно, сохраню его (хотя, я не знаю, изменилось ли это).

ответил(а) 2012-10-07T01:18:00+04:00 8 лет, 3 месяца назад
59

Это не сработало для меня. Изменение предыдущего TARGET до $$ qtLibraryTarget (...) обеспечивает правильные расширения во время сборки на разных платформах.

У меня была такая же проблема с QPluginLoader. В нескольких словах я решил: я создаю библиотеку плагинов, скажем lib1.dll, которые используют некоторые вещи из lib2.dll. В моем приложении я пытаюсь загрузить lib1 через QPluginLoader.


QPluginLoader loader( adaptersDir.absoluteFilePath(fileName) );
AdapterInterface* adapterIface = qobject_cast<AdapterInterface*>(loader.instance());

В этом случае loader.instance() возвращает 0. Решение заключалось в том, чтобы скопировать lib2.dll в папку приложения, потому что приложение использует его для правильного загрузочного модуля lib1.

ответил(а) 2012-10-29T01:48:00+04:00 8 лет, 3 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема