fix(fx-bridge): SetDllDirectoryW truoc Module::create — plugin VST3 can DLL dep canh no bi LOI 0x7E (ERROR_MOD_NOT_FOUND)

- 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)
This commit is contained in:
2026-08-22 02:45:45 +00:00
parent eecc4501bc
commit 2a4ae86f5a
+32
View File
@@ -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\<arch>\
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<ScanEntry>& 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; }