Plugin.cc 2.43 KB
#include <iostream>
#include "log4cxx/logger.h"

#include <Plugin.hh>
#include <PluginManager.hh>

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