From 9c70d949770849e446d089f52b060b54a4dbcd8d Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 11 Oct 2021 07:30:44 -0400 Subject: [PATCH] Call optional destroy() callback before unloading plugin library. --- include/plugin/callbacks.hpp | 16 ++++++++++++---- src/plugin.cpp | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/include/plugin/callbacks.hpp b/include/plugin/callbacks.hpp index bb82d20a..5c53c09d 100644 --- a/include/plugin/callbacks.hpp +++ b/include/plugin/callbacks.hpp @@ -2,9 +2,17 @@ #include -/** Called once to initialize and return the Plugin instance. -You must implement this in your plugin +/** Called immediately after loading your plugin. + +Use this to save `plugin` to a global variable and add Models to it. +Required in plugins. */ -extern "C" { +extern "C" void init(rack::plugin::Plugin* plugin); -} + +/** Called before your plugin library is unloaded. + +Optional in plugins. +*/ +extern "C" +void destroy(); diff --git a/src/plugin.cpp b/src/plugin.cpp index ac371625..db856986 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -247,8 +247,22 @@ void init() { void destroy() { for (Plugin* plugin : plugins) { - // We must delete the plugin *before* freeing the library, because the vtable of Model subclasses are static in the plugin, and we need it for the virtual destructor. void* handle = plugin->handle; + + // Call destroy() if defined in the plugin library + typedef void (*DestroyCallback)(); + DestroyCallback destroyCallback = NULL; + if (handle) { +#if defined ARCH_WIN + destroyCallback = (DestroyCallback) GetProcAddress((HMODULE) handle, "destroy"); +#else + destroyCallback = (DestroyCallback) dlsym(handle, "destroy"); +#endif + } + if (destroyCallback) + destroyCallback(); + + // We must delete the Plugin instance *before* freeing the library, because the vtables of Model subclasses are defined in the library, which are needed in the Plugin destructor. delete plugin; // Free library handle