0

I am making VST audio plugin alone with a standalone exe, both share most part of code, and I am trying to make a popup window using Qt Quick.

At the very beginning, I copied Qt DLLs from installation's bin folder to the folder of my binaries, but NOT copying anything from plugins and qml folder. The popup window works properly in exe version; but for the VST version, it claims that the DLL for QtQuick.Controls cannot be loaded. Some debug output to Visual Studio is attached below:

“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 句柄无效。

Strangely, the DLL has already been loaded, but suddenly unloaded

After some efforts, I found windeployqt would collect all stuffs you need to run a Qt program. Then I run it with:

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

After this operation, the things got worse: now both exe and VST cannot find platform DLL. However I can see the platform DLL file is just at platforms/qwindowsd.dll, in the same directory of other collected Qt DLL files.

In addition, I found the Qt5Cored.dll is modified by windeployqt, as its mod time is changed. And I found an option --no-patchqt to not patching Qt5Core library. What is the patching used for?

jiandingzhe
  • 1,881
  • 15
  • 35
  • Usually, when you place all your dependent dlls in the same folder as the plugin.dll, it works. Don't know how to undo the windeployqt action. – obiwanjacobi Feb 18 '19 at 11:06
  • You mention that you see the platform plugin dll but it has a `d` suffix, which is a debug version. Are the non-`d` version also there, and/or are you trying to run/deploy a debug version of your exe/plugin dll? Generally for Windows you just need the used Qt DLLs in the same folder as the program binary, and then the plugin subfolder(s) right below that. Usually no other magic needed. – Maxim Paperno Feb 18 '19 at 18:06
  • @obiwanjacobi Yes, the Qt dlls and the `plugins` folder are on the same folder of my DLL. – jiandingzhe Feb 19 '19 at 02:01
  • @MaxPaperno Yes my dll and exe are debug version. The Qt DLLs and the `plugins` folder are on the same folder of my binary. – jiandingzhe Feb 19 '19 at 02:03
  • To be clear, you want the _contents_ of the `plugins` folder in the same folder as the binary, *not* the actual `plugins` folder itself. So for example the `platforms` folder is at the same level as the binary (and main Qt DLLs). Should be `\platforms\qwindowsd.dll` (which I think it what you have, but just to make sure). You could also examine your exe/dll with a dependency analyzer tool, eg. `depends.exe` which comes with some Windows SDKs/dev tools, or something like http://www.dependencywalker.com/ . – Maxim Paperno Feb 19 '19 at 04:14
  • @MaxPaperno I made a typo, the `platforms` folder is on same directory of my binaries. Also I appended more details to my question. – jiandingzhe Feb 19 '19 at 07:03
  • 1
    Interesting, I didn't know about the patching. Looked into it a bit... The `windeployqt` [docs](https://doc.qt.io/Qt-5/windows-deployment.html) say: "The hardcoded local paths in Qt5Core.dll are furthermore replaced with relative ones." Looking into the [code](https://code.woboq.org/qt5/qttools/src/windeployqt/main.cpp.html#1465) and [code](https://code.woboq.org/qt5/qttools/src/shared/winutils/utils.cpp.html#987), it replaces `qt_prfxpath=` with `qt_prfxpath=.`. But why that is done, I don't know. I've deployed most Qt apps w/out `windeployqt` and haven't had an issue. – Maxim Paperno Feb 19 '19 at 07:53
  • @MaxPaperno I partially fixed the problem by adding library path/plugin path/import path before creating Qt objects. Though I still not solved the symbols error. – jiandingzhe Feb 20 '19 at 05:30

1 Answers1

0

After diving into Qt source code, I partially solved the problem by adding search paths before creating Qt objects.

The platform DLLs are searched in platforms subdirectory in each library path, which is referred in QFactoryLoader::update() method in qfactoryloader.cpp, instanced in Q_GLOBAL_STATIC_WITH_ARGS in beginning of qplatformintegrationfactory.cpp. Qt system would fill library paths with current working directory. However, the directory containing your DLLs is not referred at all. So you have to feed it to Qt system before create anything.

As we are using JUCE to develop VST, the DLL's path can be added by:

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

Also, you have to feed it to QML library search path:

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();

However, this still did not solve the failure of sudden unloading QtQuick.Controls DLL, it may have "deeper" reasons.

jiandingzhe
  • 1,881
  • 15
  • 35
  • I was answering https://stackoverflow.com/questions/57780931/gitlab-postgresql-role-gitlab-does-not-exist when you deleted it – VonC Sep 04 '19 at 04:44