В настоящее время я работаю над проектом Qt, где динамическая загрузка плагина является центральной. Я загружаю DLL с помощью Qt's QPluginLoader. Различные плагины доступны через CameraPluginStructs, определяется следующим образом:QPluginLoader.instance() - как это работает?
struct CameraPluginStruct
{
QString name;
QString filePath;
CameraPluginInterface* plugin;
QPluginLoader* pluginLoader;
CameraPluginStruct(QString filePath=nullptr, QString name=nullptr):
filePath(filepath), name(name), plugin(nullptr), pluginLoader(nullptr){}
};
Чтобы загрузить плагин, следующая функция называется:
void loadPlugin(CameraPluginStruct& p)
{
p.pluginLoader = new QPluginLoader(p.filePath);
p.pluginLoader->load();
QObject* possiblePlugin = p.pluginLoader->instance(); //QPluginLoader.instance();
if(possiblePlugin)
{
// cast from QObject to correct type:
p.plugin = qobjectcast<CameraPluginInterface>(possiblePlugin);
}
}
И выгрузить плагин, я использую эту функцию:
void unloadPlugin(CameraPluginStruct& p)
{
p.pluginLoader->unload(); // QPluginLoader.unload();
p.pluginLoader->~QPluginLoader();
p.pluginLoader = nullptr;
p.plugin = nullptr;
}
Я создал несколько простых тестовых плагинов, которые пишут сообщения на консоль при вызове конструктора. Для простоты предположим, что у меня есть два тестовых плагина: DLL A и DLL B. Когда я загружаю A, используя функцию loadPlugin() , вызывается конструктор в плагине, и соответствующее сообщение записывается в консоль. Я могу сделать то же самое с B, и все, кажется, работает - сообщение конструктора B написано на консоль, и другие функции, похоже, тоже работают.
Проблема возникает, когда я пытаюсь создать еще один CameraPluginStruct, подключенный к A или B. На консоль не записывается сообщение, что заставляет меня думать, что конструктор не вызван. Несмотря на это, я с успехом могу назвать другие тестовые функции в плагине (DoSomething(), см. Ниже). Если я выгружу все CameraPlugins, подключенные к A или B, а затем снова загрузите DLL, конструктор снова будет вызван при первом загрузке.
QPluginLoader.instance() вызов описывается следующим образом в документации:
«Возвращает объект корневой компонент плагина (...) Объект компонента является QObject.. Используйте qobject_cast() для доступа к интерфейсам, которые вы заинтересованы в . "http://doc.qt.io/qt-5/qpluginloader.html#instance
не это тогда бы естественно, что конструктор в DLL будет вызываться каждый раз, и не только в первый раз?
Как я понял, DLL загружается только один раз для любой программы. Поэтому я также попытался использовать только один QPluginLoader за DLL-файл с таким же результатом. Qt также говорит, что:
«Несколько экземпляров QPluginLoader могут использоваться для доступа к одному и тому же физическому плагину».http://doc.qt.io/qt-5/qpluginloader.html#details
Поэтому я не могу понять, как это может быть источником проблемы в любом случае.
Я был бы очень признателен, если бы кто-нибудь мог прояснить, как работает QPluginLoader.instance(). Почему конструктор - по крайней мере, как это кажется - называется только в первый раз, когда я использую вызов ()?
Спасибо!
Вот код найден в библиотеки DLL (выходные тексты различаются в А и В):
TestDLL::TestDLL()
{
std::cout << "This is written from the constructor in A \n";
}
QString TestDLL::Name() const
{
return "Hello, writing from Name() \n";
}
void TestDLL::DoSomething() const
{
qDebug() << "Hello, this text comes from DoSomething()"\n;
}
Это старый поток, но все же я заметил, что вы не используете 'qobject_cast' совершенно правильно. Всякий раз, когда вы используете 'qobject_cast',' dynamic_cast' и т. Д., Вы всегда должны проверять результат этого кастинга. Если кастинг завершился неудачно, 'qobject_cast' возвращает 0. В вашем случае у вас есть' possiblePlugin', и для меня кажется, что если он неравный 0, вы думаете, что у вас определенно есть плагин вашего типа, что может быть не всегда так. – rbaleksandar