2

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

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

当我在 3rd 方应用程序中加载我的 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 一起加载(在这种情况下,QApplication 对象可能已经存在),并且创建 QApplication 对象的 DLL 保持加载在内存中以避免其他 DLL 使用进程不再可用的内存。

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

4

2 回答 2

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 的正确位置(至少对于我的用例而言)。我认为问题在于我的第 3 方应用程序只调用了一次 DllMain,并且在应用程序退出之前不会卸载 DLL。因此,当我启动我的插件然后将其关闭然后再次启动它时,通过调用 pluginInstance 初始化的 QApplication 仍然存在。我认为我的第 3 方应用程序每次启动插件时都会启动单独的线程,所以当我第二次启动插件时,它是一个新线程,但仍在尝试使用 DllMain 中的原始 QApplication 设置(DLL 仍在加载)。因此我的错误是因为它是试图写入 GUI 的新线程。

我正在构建的第 3 方 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 文档)。

于 2011-03-01T23:23:20.400 回答
0

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

于 2011-02-25T02:03:23.637 回答