Не удается найти DLL плагина платформы после запуска windeployqt

Я делаю плагин VST audio в одиночку с автономным исполняемым файлом, оба используют большую часть кода, и я пытаюсь создать всплывающее окно с помощью Qt Quick.

В самом начале я скопировал библиотеки Qt DLL из папки установки bin в папку моих бинарников, но НЕ ничего не копировал из папок plugins и qml. Всплывающее окно корректно работает в exe-версии; но для версии VST утверждается, что DLL для QtQuick.Controls не может быть загружена. Некоторые выходные данные отладки для Visual Studio приложены ниже:

“vsthost.exe”(Win32): 已加载“D:\development\Qt\5.10.1\msvc2017_64\qml\QtQuick\Controls.2\qtquickcontrols2plugind.dll”。已加载符号。
“vsthost.exe”(Win32): 已卸载“D:\development\Qt\5.10.1\msvc2017_64\qml\QtQuick\Controls.2\qtquickcontrols2plugind.dll”
file:///D:/my_project_folder/ParamPopForm.ui.qml:2:1: plugin cannot be loaded for module "QtQuick.Controls": Cannot load library D:\development\Qt\5.10.1\msvc2017_64\qml\QtQuick\Controls.2\qtquickcontrols2plugind.dll: (some messy broken characters)
     import QtQuick.Controls 2.3 
     ^
windows\dwm\dwmapi\attribute.cpp(92)\dwmapi.dll!00007FFC62FC594E: (caller: 00007FFC62D8071A) ReturnHr(31) tid(79c) 80070006 句柄无效。
windows\dwm\dwmapi\attribute.cpp(92)\dwmapi.dll!00007FFC62FC594E: (caller: 00007FFC62D8071A) ReturnHr(32) tid(79c) 80070006 句柄无效。
windows\dwm\dwmapi\attribute.cpp(92)\dwmapi.dll!00007FFC62FC594E: (caller: 00007FFC62D8071A) ReturnHr(33) tid(79c) 80070006 句柄无效。
windows\dwm\dwmapi\attribute.cpp(92)\dwmapi.dll!00007FFC62FC594E: (caller: 00007FFC62D8071A) ReturnHr(34) tid(79c) 80070006 句柄无效。
windows\dwm\dwmapi\attribute.cpp(92)\dwmapi.dll!00007FFC62FC594E: (caller: 00007FFC62D8071A) ReturnHr(35) tid(79c) 80070006 句柄无效。
windows\dwm\dwmapi\attribute.cpp(92)\dwmapi.dll!00007FFC62FC594E: (caller: 00007FFC62D8071A) ReturnHr(36) tid(79c) 80070006 句柄无效。

Странно, DLL уже была загружена, но вдруг выгрузилась

После некоторых усилий я обнаружил, что windeployqt соберет все, что вам нужно для запуска программы Qt. Затем я запускаю его с помощью:

D:\development\Qt\5.10.1\msvc2017_64\bin\windeployqt.exe -qmldir D:\projects\my_dir_containing_qml_file MyVstPlugin.dll

После этой операции стало еще хуже: теперь ни exe, ни VST не могут найти платформенную DLL. Однако я вижу, что файл DLL платформы находится только в platforms/qwindowsd.dll, в том же каталоге, что и другие собранные файлы Qt DLL.

Кроме того, я обнаружил, что Qt5Cored.dll изменен windeployqt, так как время модификации изменено. И я нашел вариант --no-patchqt не патчить библиотеку Qt5Core. Для чего используется патч?


person jiandingzhe    schedule 18.02.2019    source источник
comment
Обычно, когда вы помещаете все свои зависимые dll в ту же папку, что и plugin.dll, это работает. Не знаю, как отменить действие windeployqt.   -  person obiwanjacobi    schedule 18.02.2019
comment
Вы упомянули, что видите dll плагина платформы, но он имеет суффикс d, который является отладочной версией. Есть ли версия, отличная от d, и/или вы пытаетесь запустить/развернуть отладочную версию вашей exe/плагина dll? Как правило, для Windows вам просто нужны используемые библиотеки Qt DLL в той же папке, что и двоичный файл программы, а затем подпапки плагинов прямо под ней. Обычно никакой другой магии не требуется.   -  person Maxim Paperno    schedule 18.02.2019
comment
@obiwanjacobi Да, dll Qt и папка plugins находятся в одной папке моей DLL.   -  person jiandingzhe    schedule 19.02.2019
comment
@MaxPaperno Да, мои dll и exe являются отладочной версией. Библиотеки Qt и папка plugins находятся в одной папке с моим двоичным файлом.   -  person jiandingzhe    schedule 19.02.2019
comment
Чтобы было ясно, вы хотите, чтобы содержимое папки plugins находилось в той же папке, что и двоичный файл, а не сама фактическая папка plugins. Так, например, папка platforms находится на том же уровне, что и двоичный файл (и основные библиотеки DLL Qt). Должно быть <bin folder>\platforms\qwindowsd.dll (что я думаю, что это то, что у вас есть, но просто чтобы убедиться). Вы также можете проверить свой exe/dll с помощью инструмента анализа зависимостей, например. depends.exe, который поставляется с некоторыми Windows SDK/инструментами разработки, или что-то вроде dependencywalker.com .   -  person Maxim Paperno    schedule 19.02.2019
comment
@MaxPaperno Я сделал опечатку, папка platforms находится в том же каталоге, что и мои двоичные файлы. Также я добавил более подробную информацию к моему вопросу.   -  person jiandingzhe    schedule 19.02.2019
comment
Интересно, я не знал о патче. Немного изучил... windeployqt документы говорят: жестко заданные локальные пути в Qt5Core.dll заменены относительными. Изучаем код и code, он заменяет qt_prfxpath=<abs path to qt install> на qt_prfxpath=.. Но зачем это сделано, я не знаю. Я развернул большинство приложений Qt без windeployqt, и у меня не было проблем.   -  person Maxim Paperno    schedule 19.02.2019
comment
@MaxPaperno Я частично исправил проблему, добавив путь к библиотеке/путь к плагину/путь импорта перед созданием объектов Qt. Хотя я до сих пор не решил ошибку символов.   -  person jiandingzhe    schedule 20.02.2019


Ответы (1)


Погрузившись в исходный код Qt, я частично решил проблему, добавив пути поиска перед созданием объектов Qt.

Библиотеки платформ ищутся в подкаталоге platforms в каждом пути к библиотеке, который указан в методе QFactoryLoader::update() в qfactoryloader.cpp, экземпляр Q_GLOBAL_STATIC_WITH_ARGS в начале qplatformintegrationfactory.cpp . Система Qt заполнит пути к библиотекам текущим рабочим каталогом. Однако каталог, содержащий ваши библиотеки DLL, вообще не упоминается. Поэтому вы должны передать его системе Qt, прежде чем что-либо создавать.

Поскольку мы используем JUCE для разработки VST, путь к DLL можно добавить:

QCoreApplication::addLibraryPath( juce::File::getSpecialLocation( juce::File::currentExecutableFile ).getParentDirectory().getFullPathName().toRawUTF8() );
app = new QGuiApplication( argc, argv );

Кроме того, вы должны передать его в путь поиска библиотеки QML:

window = new QQuickView;
window->engine()->addPluginPath( juce::File::getSpecialLocation( juce::File::currentExecutableFile ).getParentDirectory().getFullPathName().toRawUTF8() );
window->engine()->addImportPath( juce::File::getSpecialLocation( juce::File::currentExecutableFile ).getParentDirectory().getFullPathName().toRawUTF8() );
window->setGeometry( 100, 100, 400, 650 );
window->setSource( QUrl::fromLocalFile( WOL_SOURCE_DIR "/src/GUI/ParamPopForm.ui.qml" ) );
window->show();

Однако это все равно не решило проблему с внезапной выгрузкой QtQuick.Controls DLL, у нее могут быть "более глубокие" причины.

person jiandingzhe    schedule 20.02.2019
comment
Я отвечал stackoverflow.com/ вопросов/57780931/, когда вы его удалили - person VonC; 04.09.2019