we are encountering many issues with plug-ins that rely on these functions to be called upon load and unload. To make it short, when a host application loads a plug-in that also acts as a host (we have plug-ins that also act as a host, like PatchWork for example) there is no way to call these functions properly (details below).
To plug-in developers: please do not rely on these functions and use other (actually standard) mechanisms that work at the system level (local static variables or standard DllMain procedures on Windows, you name it…). That’s probably what you used to do with VST2 plug-ins anyway.
To Steinberg: would it be possible to deprecate these functions in the future? I do not see the reason for such an additional initialization mechanism that does not follow the operating system’s own dll/bundle loading and reference counting system at the process level. This would simplify the SDK and improve the reliability of VST3 plug-ins, so I guess it’s a benefit for everyone!
Details about the issue:
- If a plug-in (that also acts as a host) loads a VST3 plug-in that is also loaded by the main host application, neither the plug-in nor the main application know when the VST3 plug-in will be unloaded (both may hold references to the library while the other does not know about it, so calling the ExitDll function before the last instance of the VST3 plug-in has been unloaded in the other host will cause a crash - and NO, there is no reliable way to check the reference count before unloading. CFGetRetainCount on a Mac bundle will cause race conditions, and unless you hack Windows’ reference counting system, there is no public function to get it).
- In the same scenario, calling the Init function is possible, but tricky: you have to guess if this is the plug-in’s first load before calling this function (if the other host already loaded the plug-in, it has already been initialized), as some plug-ins do not support being called twice. It works but it is rather inelegant, and not thread safe.
- Some plug-ins actually hold a reference to themselves so that they are never unloaded (there are many reasons for this I guess, especially when using Cocoa). In this case, calling the exit function does not make sense either, and yet some plug-ins do rely on it, causing random crashes upon exit.