跨 dll 使用 QNetworkAccessManager

Posted

技术标签:

【中文标题】跨 dll 使用 QNetworkAccessManager【英文标题】:Using QNetworkAccessManager across dll 【发布时间】:2014-05-05 16:24:44 【问题描述】:

我有一个 Qt5 应用程序,它使用 QNetworkAccessManager 进行网络请求,可通过单例访问,QPluginLoader 加载扩展程序,为程序添加功能。目前我正在为插件使用静态链接,一切正常

但是,我想改用动态库来将核心功能与应用程序的其他部分分开。我已经通过宏添加了必要的declspec,并在我的 .pro 文件中进行了必要的调整。

问题是,当从 dll 中使用 QNetworkAccessManager 时,经常(比如 4 次启动中的 3 次)只返回一个空请求或空指针。没有数据,没有错误字符串,没有标题。

这是我用来加载插件的代码:

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。

【问题讨论】:

向我们展示如何使用 QNetworkAccessManager。我想你只是不等待它的回应。 @Bogdan 在应用程序的一部分中,我使用了一个使用QEventLoop 同步它的包装器。 (github.com/VeriTi/malstylerqt/blob/dll_heaven/base_app/…) 另一方面,我从QNetworkReply 异步解析一些XM。 (github.com/VeriTi/malstylerqt/blob/dll_heaven/mod_covers/blink/…) 您的来源对我来说似乎没问题。从 QNetworkAccessManager 获得 nullptr 是什么意思?如果你得到 QNetworkReplay==nullptr 那么恕我直言,这是一个 Qt 错误,你可以在没有数据但绝对没有 nullptr 的情况下进行重播(据我了解 Qt 文档)。 【参考方案1】:

好的,现在我终于调试好了。结果我在需要不同步访问的类之一中删除了内部 QNetworkAccessManager。那,更新到 Qt5.3 似乎解决了我的问题。

【讨论】:

以上是关于跨 dll 使用 QNetworkAccessManager的主要内容,如果未能解决你的问题,请参考以下文章

跨 DLL 边界使用单例 [重复]

跨dll调试

跨 DLL / 共享库使用命名空间

跨 dll 使用 QNetworkAccessManager

typeid 跨不同 dll 的结果

Type.GetType()在跨程序集反射时返回null的解决方法