我使用独立的exe单独制作VST音频插件,两者共享大部分代码,我正在尝试使用Qt Quick创建一个弹出窗口。
在一开始,我将Qt DLL从安装的bin
文件夹复制到我的二进制文件夹中,但不从plugins
和qml
文件夹中复制任何内容。弹出窗口在exe版本中正常工作;但对于VST版本,它声称无法加载QtQuick.Controls
的DLL。 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
修改,因为它的mod时间被改变了。我找到了一个选项--no-patchqt
不修补Qt5Core库。用于修补的是什么?
在深入了解Qt源代码之后,我通过在创建Qt对象之前添加搜索路径来部分解决了这个问题。
平台DLL在每个库路径的platforms子目录中搜索,在qfactoryloader.cpp中的QFactoryLoader::update()
方法中引用,在qplatswpoi开头的qplatformintegrationfactory.cpp中实例化。 Qt系统将使用当前工作目录填充库路径。但是,根本不会引用包含DLL的目录。因此,您必须在创建任何内容之前将其提供给Qt系统。
由于我们使用JUCE开发VST,因此可以通过以下方式添加DLL的路径:
Q_GLOBAL_STATIC_WITH_ARGS
此外,您必须将其提供给QML库搜索路径:
QCoreApplication::addLibraryPath( juce::File::getSpecialLocation( juce::File::currentExecutableFile ).getParentDirectory().getFullPathName().toRawUTF8() );
app = new QGuiApplication( argc, argv );
但是,这仍然没有解决突然卸载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();
DLL的失败,它可能有“更深层”的原因。