OBT::PluginLoaderImpl Class Reference

This class load / unload a plugin based on OBT::PluginInterface. More...

#include <OBTPluginLoader.h>

Collaboration diagram for OBT::PluginLoaderImpl:
[legend]

List of all members.

Public Member Functions

PluginInterfaceload (const std::string &path, const std::string &name=std::string(), const std::string &prm=std::string())
 Load the plugin library.
template<class PluginType >
PluginType * loadT (const std::string &path, const std::string &name=std::string(), const std::string &prm=std::string())
 Get the plugin object.
bool unload (PluginInterface *plugin)
 Unload the plugin.

Private Member Functions

 PluginLoaderImpl ()
 Contructor for singleton.
virtual ~PluginLoaderImpl ()
 Destructor for singleton.
No copy



 PluginLoaderImpl (const PluginLoaderImpl &)
PluginLoaderImploperator= (const PluginLoaderImpl &)

Friends

class OBT::Singleton< PluginLoaderImpl >
 Singleton is a friend to be able to call constructor.

Internal private methods



typedef bool(* InitFunc )(const char *configurationFile)
typedef bool(* FinishFunc )()
typedef const PluginInformation &(* GetInformationFunc )()
typedef PluginInterface *(* PluginGetFunc )()
typedef std::list< PluginImpl * > PluginsList
class OBT::PluginInterface
class OBT::OldPlugin
PluginsList _plugins
void unloadAndCheckForPluginDeletion (PluginImpl *pluginImpl)
template<typename FuncType >
FuncType getFunc (OBT_PLUGIN_HANDLE handle, const char *funcName) const
std::string getPath (const std::string &path, const std::string &name) const
OBT_PLUGIN_HANDLE loadCall (const char *path) const
std::string errorMsgCall () const
void unloadCall (OBT_PLUGIN_HANDLE handle) const
PluginsList::iterator find (PluginInterface *plugin)
PluginsList::iterator find (const std::string &path)

Detailed Description

This class load / unload a plugin based on OBT::PluginInterface.

Warning: This class is the implementation class, you must use the singleton OBT::PluginLoader. At the end of the application, the singleton is destroyed and automatically all the loaded plugins are unloaded.

To call a method x the syntax is

OBT::PluginLoader::getInstance().x( ... ) ;

The methods are:

The plugin is a dynamic library which declare an interface (son of OBT::PluginInterface) with OBT_EXPORT_PLUGIN_API (see How to create a plug-in object ?).

To use it see How to load a plug-in object ?.

Definition at line 45 of file OBTPluginLoader.h.


Member Typedef Documentation

typedef bool( * OBT::PluginLoaderImpl::FinishFunc)() [private]

Definition at line 139 of file OBTPluginLoader.h.

Definition at line 140 of file OBTPluginLoader.h.

typedef bool( * OBT::PluginLoaderImpl::InitFunc)(const char *configurationFile) [private]

Definition at line 138 of file OBTPluginLoader.h.

Definition at line 141 of file OBTPluginLoader.h.

typedef std::list< PluginImpl* > OBT::PluginLoaderImpl::PluginsList [private]

Definition at line 147 of file OBTPluginLoader.h.


Constructor & Destructor Documentation

OBT::PluginLoaderImpl::PluginLoaderImpl (  )  [inline, private]

Contructor for singleton.

Definition at line 121 of file OBTPluginLoader.h.

00121 {}

PluginLoaderImpl::~PluginLoaderImpl (  )  [private, virtual]

Destructor for singleton.

Unload automatically all the loaded plugins. The unloading is made in the reverse order.

Definition at line 39 of file OBTPluginLoader.cpp.

References _plugins, and unloadAndCheckForPluginDeletion().

00040 {
00041   for( PluginsList::reverse_iterator it = _plugins.rbegin() ;
00042        it != _plugins.rend() ;
00043        ++it )
00044   {
00045     ( *it )->_impl->finish() ;
00046     unloadAndCheckForPluginDeletion( *it ) ;
00047     delete *it ;
00048     *it = 0 ; // set to 0 to ease the monitoring in a debugger
00049   }
00050 }

OBT::PluginLoaderImpl::PluginLoaderImpl ( const PluginLoaderImpl  )  [private]

Member Function Documentation

std::string PluginLoaderImpl::errorMsgCall (  )  const [private]

Definition at line 129 of file OBTPluginLoader.cpp.

Referenced by load().

00130 {
00131   std::string msg ;
00132 #if !defined _MSC_VER
00133   // Error message with linux
00134   char* error = dlerror() ;
00135   if( error )
00136   {
00137     msg = "Error message from plugin: ";
00138     msg += error ;
00139     // "error" is not supposed to be free!
00140   }
00141 #endif
00142   return msg ;
00143 }

PluginLoaderImpl::PluginsList::iterator PluginLoaderImpl::find ( const std::string &  path  )  [private]

Definition at line 174 of file OBTPluginLoader.cpp.

References _plugins.

00175 {
00176   PluginsList::iterator it = _plugins.begin() ;
00177   while( it != _plugins.end() && ( *it )->_path != path )
00178   {
00179     ++it ;
00180   }
00181   return it ;
00182 }

PluginLoaderImpl::PluginsList::iterator PluginLoaderImpl::find ( PluginInterface plugin  )  [private]

Definition at line 162 of file OBTPluginLoader.cpp.

References _plugins.

Referenced by load(), and unload().

00163 {
00164   PluginsList::iterator it = _plugins.begin() ;
00165   while( it != _plugins.end() && ( *it )->_impl != plugin )
00166   {
00167     ++it ;
00168   }
00169   return it ;
00170 }

template<typename FuncType >
FuncType PluginLoaderImpl::getFunc ( OBT_PLUGIN_HANDLE  handle,
const char *  funcName 
) const [inline, private]

Definition at line 70 of file OBTPluginLoader.cpp.

00071 {
00072   void* functionPointer = 0 ;
00073   if( 0 != handle )
00074   {
00075 #ifdef _MSC_VER
00076     functionPointer = GetProcAddress( handle, funcName ) ;
00077 #else
00078     dlerror() ; // clear previous error message if any
00079     functionPointer = dlsym( handle, funcName ) ;
00080 #endif
00081   }
00082   return reinterpret_cast< FuncType >( functionPointer ) ;
00083 }

std::string PluginLoaderImpl::getPath ( const std::string &  path,
const std::string &  name 
) const [private]

defined _MSC_VER

Definition at line 87 of file OBTPluginLoader.cpp.

Referenced by load().

00088 {
00089   std::string realPath( path ) ;
00090   if( !name.empty() )
00091   {
00092 #if defined _MSC_VER
00093 #  if defined NDEBUG
00094     std::string extension( ".dll" ) ;
00095     std::string subPath( "/release/" ) ;
00096 #  else
00097     std::string extension( "_d.dll" ) ;
00098     std::string subPath( "/debug/" ) ;
00099 #  endif
00100     // first try in realPath
00101     realPath = path + "/" + name + extension ;
00102     struct stat buffer ;
00103     if( stat( realPath.c_str(), &buffer ) )
00104     { // The file doesn't exist => search in sub-directory according to the debug/release flag
00105       realPath = path + subPath + name + extension ;
00106     }
00107 #else 
00108     // try in realPath
00109     realPath = path + ( path.empty() ? "lib" : "/lib" ) + name + ".so" ;
00110 #endif
00111   }
00112   return realPath ;
00113 }

PluginInterface * PluginLoaderImpl::load ( const std::string &  path,
const std::string &  name = std::string(),
const std::string &  prm = std::string() 
)

Load the plugin library.

Parameters:
[in] path of the plugin library.
[in] name of the plugin library, default is an empty string.
[in] prm string to initialise the plugin, default is an empty string. This string is passed as the argument to the init method.
Returns:
the plugin (interface object) on success, a null pointer otherwise.

This method loads a dynamic library and then calls its init method. If the init method call of this OBT::PluginInterface returns false, the finish method is called and the plugin is immediately unloaded. Finally, a null pointer is returned.

WARNING: be sure to call unload as needed before the termination of your program. Otherwise you will experience crashes because the order of destruction for symbols may be unknown.

If the name is empty (default) the path must include the complete name and path of the plugin library (example c:\myFolder\thePlugin.dll or /usr/lib/thePlugin.so).

If the name is defined the plugin library is:

  • for Windows in debug : first try with path/name_d.dll then with path/debug/name_d.dll
  • for Windows in release : first try with path/name.dll then with path/release/name.dll
  • for Linux : path/libname.so, or if path is empty libname.so (in that case the library must be in the LD_LIBRARY_PATH)

Once the library is loaded, the init method of the plugin object is called.

Error messages see What are the error messages during a load ?. See also How to load a plug-in object ?.

Definition at line 186 of file OBTPluginLoader.cpp.

References _plugins, errorMsgCall(), find(), getPath(), loadCall(), OBT_PLUGIN_HANDLE, TRACE_ERROR, TRACE_INFO, and unloadCall().

00187 {
00188   // The plugin interface to return
00189   PluginInterface* pluginInterface = 0 ;
00190 
00191   std::string realPath( getPath( path, name ) ) ;
00192   // try to find the plugin in the list
00193   bool notLoaded = ( find( realPath ) == _plugins.end() ) ;
00194   // load the plugin if it is not already loaded
00195   OBT_PLUGIN_HANDLE pluginHandle = notLoaded ? loadCall( realPath.c_str() ) : 0 ;
00196   // Tell whether a wrapper is built around the old C-API for the current plugin
00197   bool isOldPlugin = false ;
00198 
00199   if( 0 != pluginHandle )
00200   {
00201     // Buffer error messages
00202     std::ostringstream msg ;
00203 
00204     // get the function
00205     PluginGetFunc pluginGetFunc = getFunc< PluginGetFunc >( pluginHandle, "get_OBT_PluginInterface" ) ;
00206     // get the object
00207     pluginInterface = ( 0 != pluginGetFunc ) ? pluginGetFunc() : 0 ;
00208     if( 0 == pluginInterface )
00209     {
00210       // The function "get_OBT_PluginInterface" has not been found so it is an
00211       // "old" type of plugin that has been found
00212       TRACE_INFO( "The plugin \"" << realPath
00213                   << "\" does not use a OBT::PluginInterface object "
00214                   << "to describe its entry points, build one for compatibility " ) ;
00215 
00216       // Looking for the API of an "old" plugin
00217       GetInformationFunc getInfoFunc = getFunc< GetInformationFunc >( pluginHandle, "getPluginInformation" ) ;
00218       InitFunc initFunc = getFunc< InitFunc >( pluginHandle, "initPlugin" ) ;
00219       FinishFunc finishFunc = getFunc< FinishFunc >( pluginHandle, "finishPlugin" ) ;
00220 
00221       if( 0 != getInfoFunc && 0 != initFunc && 0 != finishFunc )
00222       {
00223         pluginInterface = new OldPlugin( getInfoFunc, initFunc, finishFunc ) ;
00224         isOldPlugin = true ;
00225       }
00226       else
00227       {
00228         if( 0 == getInfoFunc ) msg << "The plugin \"" << realPath << "\" misses the \"getPluginInformation\" function\n" ;
00229         if( 0 == initFunc )    msg << "The plugin \"" << realPath << "\" misses the \"initPlugin\" function\n" ;
00230         if( 0 == finishFunc )  msg << "The plugin \"" << realPath << "\" misses the \"finishPlugin\" function\n" ;
00231       }
00232     }
00233 
00234     if( 0 == pluginInterface )
00235     {
00236       // The plugin is not of type PluginInterface, or it was not possible
00237       // to build an OldPlugin wrapper, or the path for this plugin is wrong.
00238       if( msg.str().empty() )
00239       {
00240         msg << "Unable to get the plugin object of \"" << realPath << "\"" ;
00241       }
00242     }
00243     else
00244     {
00245       if( pluginInterface->init( prm ) ) // initialization
00246       {
00247         // Initialization went well
00248         PluginImpl* impl = new PluginImpl( path, pluginHandle, pluginInterface, isOldPlugin ) ;
00249         _plugins.push_back( impl ) ;
00250       }
00251       else
00252       {
00253         msg << "Initialization of the plugin object of \"" << realPath << "\" failed" ;
00254         pluginInterface->finish() ;
00255         pluginInterface = 0 ; // The object is no more valid
00256 
00257         // unload the plugin since it cannot be used
00258         unloadCall( pluginHandle ) ;
00259       }
00260     }
00261 
00262     if( 0 == pluginInterface )
00263     {
00264       TRACE_ERROR( msg.str() ) ;
00265     }
00266   }
00267   else
00268   {
00269     // Plugin handle equals to 0 which probably means that the file to load
00270     // does not exist
00271     TRACE_ERROR( "Unable to load plugin: \"" + realPath + "\" " + errorMsgCall() ) ;
00272   }
00273   return pluginInterface ;
00274 }

OBT_PLUGIN_HANDLE PluginLoaderImpl::loadCall ( const char *  path  )  const [private]

Definition at line 117 of file OBTPluginLoader.cpp.

Referenced by load().

00118 {
00119 #if defined _MSC_VER
00120   return LoadLibrary( path ) ;
00121 #else
00122   dlerror() ; // clear previous error message if any
00123   return dlopen( path, RTLD_LAZY | RTLD_GLOBAL ) ;
00124 #endif
00125 }

template<class PluginType >
PluginType* OBT::PluginLoaderImpl::loadT ( const std::string &  path,
const std::string &  name = std::string(),
const std::string &  prm = std::string() 
) [inline]

Get the plugin object.

Parameters:
PluginType is the type of the plugin object, must be a son of OBT::PluginInterface.

For other parameters see load.

Returns:
The plugin (interface object) on success, a null pointer otherwise.

If the the library is loaded, but the plugin object is not of the PluginType type, the library is unloaded (finish method is called).

Error messages see What are the error messages during a load ?. See also How to load a plug-in object ?.

Definition at line 98 of file OBTPluginLoader.h.

References TRACE_ERROR.

00100   {
00101     PluginInterface* plugin = load( path, name, prm ) ;
00102     PluginType* pluginType = dynamic_cast< PluginType* >( plugin ) ;
00103     if( 0 != plugin && 0 == pluginType )
00104     {
00105       TRACE_ERROR( "Unable to get the plugin object of type [" << typeid( (PluginType*)0 ).name() << "] for the plugin \"" << getPath( path, name ) << "\"" ) ;
00106       unload( plugin ) ;
00107     }
00108     return pluginType ;
00109   }

PluginLoaderImpl& OBT::PluginLoaderImpl::operator= ( const PluginLoaderImpl  )  [private]
bool PluginLoaderImpl::unload ( PluginInterface plugin  ) 

Unload the plugin.

Returns:
the finish method return.

Before unloading the library, the finish method of the plugin object is called.

Definition at line 278 of file OBTPluginLoader.cpp.

References _plugins, find(), TRACE_ERROR, and unloadAndCheckForPluginDeletion().

00279 {
00280   bool ok = false ;
00281   PluginsList::iterator it = find( plugin ) ;
00282   if( it != _plugins.end() )
00283   {
00284     ok = ( *it )->_impl->finish() ;
00285     unloadAndCheckForPluginDeletion( *it ) ;
00286     delete *it ;
00287     _plugins.erase( it ) ;
00288   }
00289   else
00290   {
00291     TRACE_ERROR( "The plugin \"" << plugin << "\" is not loaded" ) ;
00292   }
00293   return ok ;
00294 }

void PluginLoaderImpl::unloadAndCheckForPluginDeletion ( PluginImpl pluginImpl  )  [private]

Definition at line 55 of file OBTPluginLoader.cpp.

References OBT::PluginImpl::_handle, OBT::PluginImpl::_impl, OBT::PluginImpl::_isOldPlugin, and unloadCall().

Referenced by unload(), and ~PluginLoaderImpl().

00056 {
00057   unloadCall( pluginImpl->_handle ) ;
00058   if( pluginImpl->_isOldPlugin )
00059   {
00060     // This plugin is of type "OldPlugin" so it has been previously allocated
00061     // and its memory needs to be free
00062     delete pluginImpl->_impl ;
00063     pluginImpl->_impl = 0 ;  // to ease debug sessions
00064   }
00065 }

void PluginLoaderImpl::unloadCall ( OBT_PLUGIN_HANDLE  handle  )  const [private]

Definition at line 147 of file OBTPluginLoader.cpp.

Referenced by load(), and unloadAndCheckForPluginDeletion().

00148 {
00149   if( 0 != handle )
00150   {
00151 #ifdef _MSC_VER
00152     FreeLibrary( handle ) ;
00153 #else
00154     dlerror() ; // clear previous error message if any
00155     dlclose( handle ) ;
00156 #endif
00157   }
00158 }


Friends And Related Function Documentation

friend class OBT::OldPlugin [friend]

Definition at line 136 of file OBTPluginLoader.h.

friend class OBT::PluginInterface [friend]

Definition at line 135 of file OBTPluginLoader.h.

friend class OBT::Singleton< PluginLoaderImpl > [friend]

Singleton is a friend to be able to call constructor.

Definition at line 119 of file OBTPluginLoader.h.


Member Data Documentation

Definition at line 150 of file OBTPluginLoader.h.

Referenced by find(), load(), unload(), and ~PluginLoaderImpl().


Generated on 1 Jan 2010 for OBT by  doxygen 1.6.1