Инструмент Qt / MFC Migration Framework: правильно ли завершается работа DLL? - PullRequest
2 голосов
/ 25 февраля 2011

Я использую инструмент Qt / MFC Migration Framework в следующем примере: 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 в том же процессе (в этом случае объект QApplication, вероятно, уже будет существовать), и что библиотека DLL, которая создает объект QApplication, остается загруженной в память, чтобы другие библиотеки DLL, использующие память, которая больше не доступна для процесса, остаются в памяти.

Поэтому мне интересно, есть ли какая-то проблема, когда мне нужно каким-то образом сохранять исходную DLL-библиотеку загруженной, несмотря ни на что?

Ответы [ 2 ]

1 голос
/ 02 марта 2011

Я ПОЛУЧИЛ ЭТУ РАБОТУ!После многих разочаровывающих часов, работая над этим, я начал работать.Я использовал код, предоставленный в документации по миграции 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;
 }

Эта структура работала бы для одной загрузки моей библиотеки подключаемых модулей, но не работала при последующих загрузках.Я не верю, что DllMain является правильным местом для вызова pluginInstance (по крайней мере, для моего варианта использования).Я думаю, что проблема заключалась в том, что мое стороннее приложение вызывает DllMain только один раз и не выгружает DLL, пока приложение не закроется.Таким образом, когда я запустил свой плагин, а затем выключил и снова запустил его, QApplication, инициализированный вызовом pluginInstance, все еще зависал.Я думаю, что мое стороннее приложение запускает отдельные потоки каждый раз, когда запускается мой плагин, поэтому, когда я запускал свой плагин во второй раз, он был новым потоком, но все еще пытался использовать исходную настройку QApplication в DllMain (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 голосов
/ 25 февраля 2011

Как я знаю, когда вы загружаете Qt DLL, приложение на основе MFC неявно загружает DLL, связанные с платформой Qt. Также, когда вы запускаете QApplication в Dll, он создает только один экземпляр QApplication. Однако, когда вы закрываете QApplication, библиотеки DLL, связанные с платформой Qt, не выгружаются из приложения на основе MFC. Одна из библиотек DLL имеет экземпляр QApplication постоянно. Лучшее решение заключается в том, что исполняемый файл не Dll.

...