2011-02-25 22 views
2

我使用Qt/MFC迁移框架工具下面这个例子: http://doc.qt.nokia.com/solutions/4/qtwinmigrate/winmigrate-qt-dll-example.htmlQt/MFC迁移框架工具:正确退出DLL?

我生成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 

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

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

The DLL also has to make sure that it can be loaded together with other Qt based DLLs in the same process (in which case a QApplication object will probably exist already), and that the DLL that creates the QApplication object remains loaded in memory to avoid other DLLs using memory that is no longer available to the process.

所以我想如果有一些问题,我需要以某种方式保留原来的DLL加载无论什么?

回答

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文档的阅读)。

0

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

+0

我认为你是对的,一个DLL永久拥有QApplication实例。当你启动一个新的DLL(或者同一个DLL)时,你如何连接到现有的QApplication实例,以便创建GUI对象? – User 2011-03-01 17:32:54