2015-04-16 4 views
1

В настоящее время я работаю над проектом 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; 
} 
+0

Это старый поток, но все же я заметил, что вы не используете 'qobject_cast' совершенно правильно. Всякий раз, когда вы используете 'qobject_cast',' dynamic_cast' и т. Д., Вы всегда должны проверять результат этого кастинга. Если кастинг завершился неудачно, 'qobject_cast' возвращает 0. В вашем случае у вас есть' possiblePlugin', и для меня кажется, что если он неравный 0, вы думаете, что у вас определенно есть плагин вашего типа, что может быть не всегда так. – rbaleksandar

ответ

1

Когда плагин загружается (т.е. первый раз QPluginLoader::instance() называется), то одного экземпляр его создан - это ваш корневой экземпляр. Корневой экземпляр - единственный экземпляр, который QPluginLoader когда-либо создаст для вас.

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

Смежные вопросы