#include #include "log4cxx/logger.h" #include #include using namespace std; namespace AMDA { namespace Plugins { /** Loads the specified plugin as a dynamic library and locates the plugin's exported functions @param sFilename Filename of the plugin to load */ Plugin::Plugin(const std::string &sFilename) try : m_hDLL(0), m_pDLLRefCount(0), m_pfnGetEngineVersion(0), m_pfnRegisterPlugin(0), m_pfnUnregisterPlugin(0), _filename(sFilename) { // Try to load the plugin as a dynamic library m_hDLL = dlopen(sFilename.c_str(), RTLD_NOW|RTLD_GLOBAL); if(!m_hDLL) { ERROR_EXCEPTION( "Plugin::Plugin: " << dlerror()); } // Locate the plugin's exported functions m_pfnGetEngineVersion = (fnGetEngineVersion *)( dlsym(m_hDLL, "getPluginVersion")); m_pfnRegisterPlugin = (fnRegisterPlugin *)( dlsym(m_hDLL, "registerPlugin")); m_pfnUnregisterPlugin = (fnUnregisterPlugin *)( dlsym(m_hDLL, "unregisterPlugin")); // If the functions aren't found, we're going to assume this is // a plain simple DLL and not one of our plugins if(!m_pfnGetEngineVersion || ! m_pfnRegisterPlugin) { ERROR_EXCEPTION( "Plugin::Plugin" << sFilename << ": is not a valid plugin"); } // Initialize a new DLL reference counter m_pDLLRefCount = new size_t(1); } catch(...) { if ( m_hDLL) dlclose(m_hDLL); throw; } /** Creates a copy of a plugin that has already been loaded. Required to provide correct semantics for storing plugins in an STL map container. @param Other Other plugin instance to copy */ Plugin::Plugin(const Plugin &Other) : m_hDLL(Other.m_hDLL), m_pDLLRefCount(Other.m_pDLLRefCount), m_pfnGetEngineVersion(Other.m_pfnGetEngineVersion), m_pfnRegisterPlugin(Other.m_pfnRegisterPlugin), m_pfnUnregisterPlugin(Other.m_pfnUnregisterPlugin) { /// Increase DLL reference counter ++*m_pDLLRefCount; } /** Destroys the plugin, unloading its library when no more references to it exist. */ Plugin::~Plugin() { // Only unload the DLL if there are no more references to it if(!--*m_pDLLRefCount) { if(m_pfnUnregisterPlugin) { m_pfnUnregisterPlugin(); } delete m_pDLLRefCount; if ( dlclose(m_hDLL) != 0 ){ LOG4CXX_WARN(gLogger, "Plugin::~Plugin: " << _filename << dlerror()); } else { LOG4CXX_DEBUG(gLogger, "Plugin::~Plugin: " << _filename << "unload"); } } } } // namespace Plugins } // namespace AMDA