Qt / MFC迁移框架工具:正确退出DLL?

时间:2011-02-25 00:54:33

标签: c++ qt mfc qt4 qt-mfc-migration

我正在使用此示例后面的Qt / MFC迁移框架工具: http://doc.qt.nokia.com/solutions/4/qtwinmigrate/winmigrate-qt-dll-example.html

我构建的DLL由第三方基于MFC的应用程序加载。第三方应用程序基本上调用我的一个导出的DLL函数来启动我的插件和另一个函数来关闭我的应用程序。目前我在关机功能中什么也没做。

当我在第三方应用程序中加载我的DLL时,调用启动函数并且我的DLL成功启动,我可以看到我的消息框。但是,如果我关闭我的插件,然后尝试再次启动它,我会收到以下错误:

Debug Error!

Program: <my 3rd party app>
Module: 4.7.1
File: global\qglobal.cpp
Line: 2262
ASSERT failure in QWidget: "Widgets must be created in the GUI
thread.", file kernel\qwidget.cpp line 1233

(Press Retry to debug the application)

Abort Retry Ignore

这让我觉得我没有做些什么来正确关闭我的插件。我需要做什么才能正确关闭它?

更新: http://doc.qt.nokia.com/solutions/4/qtwinmigrate/winmigrate-walkthrough.html说:

  

DLL还必须确保它   可以与其他Qt一起加载   基于同一进程的DLL(in   这是QApplication对象的情况   可能已经存在了),那个   创建QApplication的DLL   对象仍然在内存中加载   避免使用内存的其他DLL   该流程不再可用。

所以我想知道是否存在某些问题我需要以某种方式保持原始DLL无论如何加载?

2 个答案:

答案 0 :(得分:1)

我知道这个工作!在经历了许多令人沮丧的工作后,我开始工作了。我使用的是Qt / MFC迁移文档中提供的代码:

 BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason,
                      LPVOID /*lpvReserved*/ )
 {
     static bool ownApplication = FALSE;

     if ( dwReason == DLL_PROCESS_ATTACH )
         ownApplication = QMfcApp::pluginInstance( hInstance );
     if ( dwReason == DLL_PROCESS_DETACH && ownApplication )
         delete qApp;

     return TRUE;
 }

此结构适用于我的插件DLL的单个加载,但在后续加载时失败。我不相信DllMain是调用pluginInstance的正确位置(至少对我的用例来说)。我认为问题是我的第三方应用程序只调用DllMain一次,并且在应用程序退出之前不会卸载DLL。因此,当我启动插件然后将其关闭然后再次启动时,通过调用pluginInstance初始化的QApplication仍然存在。我认为我的第三方应用程序每次启动插件时都会启动单独的线程,所以当我第二次启动插件时它是一个新线程但仍尝试使用DllMain中的原始QApplication设置(DLL仍在加载)。因此我的错误是因为它是尝试写入GUI的新线程。

我正在构建的第三方MFC应用程序需要在我的DLL,Startup()和Shutdown()中进行两次导出,并在相关时间调用它。

因此,我没有按照演练的建议进行操作,而是执行以下操作(伪代码):

extern "C" __declspec(dllexport) void Startup()
{
  QMfcApp::pluginInstance( 3rdPartyApp::GetPluginHandle() );
  QWinWidget win( 3rdPartyApp::GetParentWindow() );
  win.showCentered();
  QMessageBox::about( &win, "About", "Hello World" );
}

 extern "C" __declspec(dllexport) void Shutdown()
{
  qApp->quit();
  delete qApp;
}

这对于单个插件来说很好,但是如果我创建多个插件,我不确定这会有多好,因为事件循环集成我觉得应该只有一个QApplication跨所有插件(基于我的阅读) Qt / MFC文件)。

答案 1 :(得分:0)

据我所知,当你加载Qt DLL时,基于MFC的应用程序隐式加载与Qt框架相关的DLL。此外,当您在Dll中启动QApplication时,它只生成一个QApplication实例。但是,当您关闭QApplication时,与Qt框架相关的Dll不会从基于MFC的应用程序中卸载。其中一个DLL永久有QApplication实例。最佳解决方案是可执行文件而不是Dll。