2011-02-25 61 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