2

次の例に従って、Qt / MFC移行フレームワークツールを使用しています:http: //doc.qt.nokia.com/solutions/4/qtwinmigrate/winmigrate-qt-dll-example.html

私が作成したdllは、サードパーティのMFCベースのアプリケーションによってロードされます。サードパーティのアプリは基本的に、エクスポートされたDLL関数の1つを呼び出してプラグインを起動し、別の関数を呼び出してアプリケーションをシャットダウンします。現在、シャットダウン機能では何もしていません。

サードパーティのアプリに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を呼び出す正しい場所だとは思いません(少なくとも私のユースケースでは)。問題は、サードパーティのアプリがDllMainを1回だけ呼び出し、アプリケーションが終了するまでDLLをアンロードしないことだと思います。したがって、プラグインを起動してからシャットダウンしてから再度起動したとき、pluginInstanceの呼び出しによって初期化されたQApplicationはまだハングしていました。プラグインを起動するたびにサードパーティのアプリが別々のスレッドを起動すると思うので、2回目にプラグインを起動したときは新しいスレッドでしたが、DllMainで元のQApplicationセットアップを使用しようとしました(DLLはまだロードされています)。したがって、GUIに書き込もうとしている新しいスレッドであるため、エラーが発生しました。

私が構築しているサードパーティのMFCアプリは、DLLにStartup()とShutdown()の2つのエクスポートを想定しており、これらは関連する時間に呼び出されます。

したがって、ウォークスルーが示唆することを行う代わりに、私は次のようにしました(擬似コード):

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;
}

これは単一のプラグインには問題ありませんが、複数のプラグインを作成する場合、イベントループの統合により、これがどの程度うまく機能するかわかりません。すべてのプラグインに1つのQApplicationのみが存在する必要があると思います(Qtの読み取りに基づく) / MFCドキュメント)。

于 2011-03-01T23:23:20.400 に答える
0

私が知っているように、Qt DLLをロードすると、MFCベースのアプリケーションはQtフレームワークに関連するDLLを暗黙的にロードします。また、DLLでQApplicationを起動すると、QApplicationインスタンスが1つだけ作成されます。ただし、QApplicationをシャットダウンすると、Qtフレームワークに関連するDLLはMFCベースのアプリケーションからアンロードされません。DLLの1つにQApplicationインスタンスが永続的にあります。最善の解決策は、DLLではなく実行可能ファイルです。

于 2011-02-25T02:03:23.637 に答える