#include "b3PluginManager.h" #include "Bullet3Common/b3HashMap.h" #include "Bullet3Common/b3ResizablePool.h" #include "plugins/b3PluginAPI.h" #include "SharedMemoryPublic.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include typedef HMODULE B3_DYNLIB_HANDLE; #define B3_DYNLIB_OPEN LoadLibrary #define B3_DYNLIB_CLOSE FreeLibrary #define B3_DYNLIB_IMPORT GetProcAddress #else #include typedef void* B3_DYNLIB_HANDLE; #define B3_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL) #define B3_DYNLIB_CLOSE dlclose #define B3_DYNLIB_IMPORT dlsym #endif struct b3Plugin { B3_DYNLIB_HANDLE m_pluginHandle; std::string m_pluginPath; PFN_INIT m_initFunc; PFN_EXIT m_exitFunc; PFN_EXECUTE m_executeCommandFunc; void clear() { B3_DYNLIB_CLOSE(m_pluginHandle); m_pluginHandle = 0; m_initFunc = 0; m_exitFunc = 0; m_executeCommandFunc = 0; } }; typedef b3PoolBodyHandle b3PluginHandle; struct b3PluginManagerInternalData { b3ResizablePool m_plugins; b3HashMap m_pluginMap; }; b3PluginManager::b3PluginManager() { m_data = new b3PluginManagerInternalData; } b3PluginManager::~b3PluginManager() { m_data->m_pluginMap.clear(); m_data->m_plugins.exitHandles(); delete m_data; } int b3PluginManager::loadPlugin(const char* pluginPath) { int pluginUniqueId = -1; b3Plugin* plugin = m_data->m_pluginMap.find(pluginPath); if (plugin) { //already loaded } else { pluginUniqueId = m_data->m_plugins.allocHandle(); b3PluginHandle* plugin = m_data->m_plugins.getHandle(pluginUniqueId); B3_DYNLIB_HANDLE pluginHandle = B3_DYNLIB_OPEN(pluginPath); bool ok = false; if (pluginHandle) { plugin->m_initFunc = (PFN_INIT)B3_DYNLIB_IMPORT(pluginHandle, "initPlugin"); plugin->m_exitFunc = (PFN_EXIT)B3_DYNLIB_IMPORT(pluginHandle, "exitPlugin"); plugin->m_executeCommandFunc = (PFN_EXECUTE)B3_DYNLIB_IMPORT(pluginHandle, "executePluginCommand"); if (plugin->m_initFunc && plugin->m_exitFunc && plugin->m_executeCommandFunc) { int version = plugin->m_initFunc(); if (version == SHARED_MEMORY_MAGIC_NUMBER) { ok = true; plugin->m_pluginHandle = pluginHandle; plugin->m_pluginPath = pluginPath; m_data->m_pluginMap.insert(pluginPath, *plugin); } else { int expect = SHARED_MEMORY_MAGIC_NUMBER; b3Warning("Warning: plugin is wrong version: expected %d, got %d\n", expect, version); } } else { b3Warning("Loaded plugin but couldn't bind functions"); } if (!ok) { B3_DYNLIB_CLOSE(pluginHandle); } } else { b3Warning("Warning: couldn't load plugin %s\n", pluginPath); } if (!ok) { m_data->m_plugins.freeHandle(pluginUniqueId); pluginUniqueId = -1; } } return pluginUniqueId; } void b3PluginManager::unloadPlugin(int pluginUniqueId) { b3PluginHandle* plugin = m_data->m_plugins.getHandle(pluginUniqueId); if (plugin) { plugin->m_exitFunc(); m_data->m_pluginMap.remove(plugin->m_pluginPath.c_str()); m_data->m_plugins.freeHandle(pluginUniqueId); } } int b3PluginManager::executePluginCommand(int pluginUniqueId, const char* arguments) { int result = -1; b3PluginHandle* plugin = m_data->m_plugins.getHandle(pluginUniqueId); if (plugin) { result = plugin->m_executeCommandFunc(arguments); } return result; }