From 2a4ae86f5ad419685511ddc327dbd976402c16a9 Mon Sep 17 00:00:00 2001 From: locpham Date: Sat, 22 Aug 2026 02:45:45 +0000 Subject: [PATCH] =?UTF-8?q?fix(fx-bridge):=20SetDllDirectoryW=20truoc=20Mo?= =?UTF-8?q?dule::create=20=E2=80=94=20plugin=20VST3=20can=20DLL=20dep=20ca?= =?UTF-8?q?nh=20no=20bi=20LOI=200x7E=20(ERROR=5FMOD=5FNOT=5FFOUND)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SDK module_win32 LoadLibraryW khong search thu muc plugin cho dependency DLLs - setPluginSearchPath: bundle folder -> Contents/x86_64-win; file don -> parent dir - ap dung ca render (vst3FxLoadInner) lan scan (scanModuleInner) - test: ~30 plugin iZotope/RX load OK; Melodyne COM 0x80010106 la plugin dac thu (STA+license) --- native_bridge/src/RenderFxJob.cpp | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/native_bridge/src/RenderFxJob.cpp b/native_bridge/src/RenderFxJob.cpp index cc6e4a0..5b6bef6 100644 --- a/native_bridge/src/RenderFxJob.cpp +++ b/native_bridge/src/RenderFxJob.cpp @@ -394,9 +394,38 @@ bool pickFxClass(const VST3::Hosting::PluginFactory& factory, } // Must live OUTSIDE any __try (C2712: no C++ unwinding inside SEH frames). +// Windows DLL search: LoadLibraryW (VST3 SDK) does NOT search the plugin's own +// directory for dependency DLLs -> ERROR_MOD_NOT_FOUND (0x7E) when a VST3 needs +// helper DLLs next to it (bundle Contents\x86_64-win or sidecar files). Point +// the DLL search path at the plugin directory before Module::create. +#ifdef _WIN32 +static void setPluginSearchPath(const std::string& path) { + std::string dir; + namespace fs = std::filesystem; + try { + fs::path p(path); + // Folder bundle (.vst3 dir): deps live in Contents\\ + if (fs::is_directory(p)) { + dir = (p / "Contents" / "x86_64-win").string(); + if (!fs::is_directory(dir)) dir = (p / "Contents").string(); + } else { + dir = p.parent_path().string(); // single-file .vst3 / .dll + } + } catch (...) { return; } + if (dir.empty()) return; + // SetDllDirectoryW is process-global, fine here: bridge loads one plugin + // at a time (render slots serial; realtime chain loads on its own thread). + SetDllDirectoryW(std::wstring(dir.begin(), dir.end()).c_str()); + std::cerr << "[RenderFx] dll search dir: " << dir << std::endl; +} +#endif + bool vst3FxLoadInner(Vst3FxState* s, const std::string& path, double sampleRate, int32 maxBlockSize, std::string& err) { using namespace VST3::Hosting; +#ifdef _WIN32 + setPluginSearchPath(path); +#endif Module::Ptr module = Module::create(path, err); if (!module) return false; const PluginFactory& factory = module->getFactory(); @@ -1457,6 +1486,9 @@ struct ScanEntry { // is caught by safeScanModule's SEH and skipped, not fatal to the whole scan. bool scanModuleInner(const std::string& path, std::vector& out) { using namespace VST3::Hosting; +#ifdef _WIN32 + setPluginSearchPath(path); // deps cạnh plugin (0x7E fix) — scan cũng load module +#endif std::string err; Module::Ptr module = Module::create(path, err); if (!module) { std::cerr << "[Scan] skip (module load failed): " << path << " — " << err << std::endl; return false; }