This class load / unload a plugin based on OBT::PluginInterface. More...
#include <OBTPluginLoader.h>
Public Member Functions | |
PluginInterface * | load (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 &) | |
PluginLoaderImpl & | operator= (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) |
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.
typedef bool( * OBT::PluginLoaderImpl::FinishFunc)() [private] |
Definition at line 139 of file OBTPluginLoader.h.
typedef const PluginInformation&( * OBT::PluginLoaderImpl::GetInformationFunc)() [private] |
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.
typedef PluginInterface*( * OBT::PluginLoaderImpl::PluginGetFunc)() [private] |
Definition at line 141 of file OBTPluginLoader.h.
typedef std::list< PluginImpl* > OBT::PluginLoaderImpl::PluginsList [private] |
Definition at line 147 of file OBTPluginLoader.h.
OBT::PluginLoaderImpl::PluginLoaderImpl | ( | ) | [inline, private] |
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] |
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.
PluginLoaderImpl::PluginsList::iterator PluginLoaderImpl::find | ( | PluginInterface * | plugin | ) | [private] |
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.
[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. |
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:
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().
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.
PluginType | is the type of the plugin object, must be a son of OBT::PluginInterface. |
For other parameters see load.
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.
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().
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.
PluginsList OBT::PluginLoaderImpl::_plugins [private] |
Definition at line 150 of file OBTPluginLoader.h.
Referenced by find(), load(), unload(), and ~PluginLoaderImpl().