Использование QNetworkAccessManager через dll

У меня есть приложение Qt5, которое использует QNetworkAccessManager для сетевых запросов, доступных через синглтон, и QPluginLoader для загрузки расширений, добавляющих функциональность программе. В настоящее время я использую статическое связывание для плагинов, и все работает просто отлично.

Однако я хочу переключиться на использование динамических библиотек, чтобы отделить основные функции от других частей приложения. Я добавил необходимые declspec с помощью макроса и внес необходимые коррективы в мои файлы .pro.

Проблема в том, что очень часто (например, 3 из 4 запусков) QNetworkAccessManager при использовании из dll просто возвращает пустой запрос или нулевой указатель. Нет данных, нет строки ошибки, нет заголовков.

Это код, который я использую для загрузки плагинов:

template <typename PluginType>
static QList<PluginType*> loadModules() {
    QList<PluginType*> loadedModules;
    foreach (QObject* instance, QPluginLoader::staticInstances()) {
        PluginType* plugin = qobject_cast<PluginType*>(instance);
        if (plugin) {
            loadedModules << plugin;
        }
    }
    QDir modulesDir(qApp->applicationDirPath() + "/modules");
    foreach (QString fileName, modulesDir.entryList(QDir::Files)) {
        QPluginLoader loader(modulesDir.absoluteFilePath(fileName));
        QObject *instance = loader.instance();
        PluginType* plugin = qobject_cast<PluginType*>(instance);
        if (plugin) {
            loadedModules << plugin;
        }
    }
    return loadedModules;
}

Который используется в этой нестатической перегрузке без шаблона, вызываемой во время запуска:

bool AppController::loadModules() {
m_window = new AppWindow();
/* some unimportant connection and splashscreen updating */
QList <ModuleInterface*> loadedModules = loadModules<ModuleInterface>();
foreach (ModuleInterface* module, loadedModules) {
    m_splash->showMessage(tr("Initializing module: %1").arg(module->getModuleName()),
                          Qt::AlignBottom | Qt::AlignRight, Qt::white);
    module->preinit();
    QApplication::processEvents();
    // [1]
    ControllerInterface *controller = module->getMainController();
    m_window->addModule(module->getModuleName(),
                        QIcon(module->getIconPath()),
                        controller->primaryWidget(),
                        controller->settingsWidget());
    m_moduleControllers << controller;
}
m_window->addGeneralSettings((new GeneralSettingsController(m_window))->settingsWidget());
m_window->enableSettings();
/* restoring window geometry & showing it */
return true;
}

Однако, если я вставлю QThread::sleep(1); в строку с пометкой 1, все работает нормально, но загрузка замедляется, и я очень сомневаюсь, что это стабильное решение, которое будет работать везде. Кроме того, я отправляю запросы на сайт MyAnimeList.


person Oleg Pyzhcov    schedule 05.05.2014    source источник
comment
Покажите нам, как вы используете QNetworkAccessManager. Я полагаю, вы просто не ждете его ответа.   -  person Bogdan    schedule 06.05.2014
comment
@Bogdan В одной части приложения я использую оболочку, которая синхронизирует его с помощью QEventLoop. (github.com/VeriTi/malstylerqt/blob/dll_heaven/base_app /) В другом я асинхронно анализирую некоторые XM из QNetworkReply. (github.com/VeriTi/malstylerqt/blob/dll_heaven/mod_covers /мигает/)   -  person Oleg Pyzhcov    schedule 07.05.2014
comment
Ваш источник кажется мне нормальным. Что вы имеете в виду, когда получаете nullptr от QNetworkAccessManager? Если вы получаете QNetworkReplay==nullptr, то IMHO это ошибка Qt, вы можете получить повтор без данных, но определенно без nullptr (насколько я понимаю документ Qt).   -  person Bogdan    schedule 07.05.2014


Ответы (1)


Хорошо, теперь я, наконец, отладил его. Оказалось, что я удалил внутренний QNetworkAccessManager в одном из классов, которым требовался несинхронизирующий доступ. Это и обновление до Qt5.3, похоже, решили мою проблему.

person Oleg Pyzhcov    schedule 25.05.2014