00001 #ifndef __NITRO_PLUGIN_INTERFACE_H__
00002 #define __NITRO_PLUGIN_INTERFACE_H__
00003
00004 #include <map>
00005 #include <string>
00006 #include <utility>
00007 #include <iostream>
00008
00009 #include <loaders/dynamic_lib_loader.h>
00010 #include <utilities/shared_pointer.h>
00011
00012 #ifdef PLUGIN_COMPILATION
00013
00014 #define BEGIN_PLUGIN_DECLARATION()\
00015 void * GetObject( const char * InterfaceType , const std::string & SafeObjectName );\
00016 static std::map< std::string , std::map< std::string , nitro::SharedPointerInterface * > > ExportedObjects;\
00017 EXTERN_C NITRO_EXPORTING void ReleaseInterface( void * Interface )\
00018 {\
00019 for( std::map< std::string , std::map< std::string , nitro::SharedPointerInterface * > >::iterator i( ExportedObjects.begin() ) ;\
00020 i != ExportedObjects.end() ; ++i )\
00021 {\
00022 for( std::map< std::string , nitro::SharedPointerInterface * >::iterator j( i->second.begin() ) ; \
00023 j != i->second.end() ; ++j )\
00024 {\
00025 void * d( j->second->GetDataAddress() );\
00026 if( Interface == j->second->GetDataAddress() )\
00027 {\
00028 delete j->second;\
00029 i->second.erase( j );\
00030 return;\
00031 }\
00032 }\
00033 }\
00034 }\
00035 EXTERN_C NITRO_EXPORTING void * GetInterface( const char * InterfaceType , const char * ObjectName )\
00036 {\
00037 if( ExportedObjects.find( std::string( InterfaceType ) ) == ExportedObjects.end() )\
00038 {\
00039 ExportedObjects.insert( std::pair< std::string , std::map< std::string , nitro::SharedPointerInterface * > >( std::string( InterfaceType ) , std::map< std::string , nitro::SharedPointerInterface * >() ) );\
00040 }\
00041 std::string SafeObjectName( ObjectName == NULL ? "" : ObjectName );\
00042 if( ExportedObjects.find( std::string( InterfaceType ) )->second.find( SafeObjectName ) == \
00043 ExportedObjects.find( std::string( InterfaceType ) )->second.end() )\
00044 {\
00045 GetObject( InterfaceType , SafeObjectName );\
00046 }\
00047 return( ExportedObjects.find( std::string( InterfaceType ) )->second.find( SafeObjectName )->second->GetDataAddress() );\
00048 }\
00049 void * GetObject( const char * InterfaceType , const std::string & SafeObjectName )\
00050 {
00051
00052 #define DECLARE_PLUGIN_INTERFACE( OriginalType , ExportedType )\
00053 if( std::string( InterfaceType ) == typeid( OriginalType ).name() )\
00054 {\
00055 OriginalType * Ret( new OriginalType() );\
00056 ExportedObjects.find( std::string( InterfaceType ) )->second.insert( std::pair< std::string , nitro::SharedPointerInterface * >( SafeObjectName , new nitro::SharedPointer< OriginalType >( Ret ) ) );\
00057 return( ( ExportedType * )Ret );\
00058 }
00059
00060 #define END_PLUGIN_DECLARATION()\
00061 throw( nitro::exception( std::string( "Type \"" ) + InterfaceType + "\" is not exported by the plugin" , 1 ) );\
00062 }
00063
00064 #else
00065
00066 #define BEGIN_PLUGIN_DECLARATION()
00067
00068 #define DECLARE_PLUGIN_INTERFACE( OriginalType , ExportedType )
00069
00070 #define END_PLUGIN_DECLARATION()
00071
00072 #endif
00073
00074 namespace nitro
00075 {
00094 class PluginInterface{
00095
00096 public:
00097
00120 static bool IsPlugin( nitro::DynamicLibLoader & Module );
00121
00144 template< class type1 >static bool InterfaceExported( nitro::DynamicLibLoader & Plugin );
00145
00176 template< class type1 >static type1 * GetInterface( nitro::DynamicLibLoader & Plugin , const std::string & ObjectName = "" );
00177
00204 template< class type1 >static type1 * GetNewInterface( nitro::DynamicLibLoader & Plugin );
00205
00232 template< class type1 >static void ReleaseInterface( nitro::DynamicLibLoader & Plugin , type1 * Interface );
00233
00234 private:
00235
00246 static std::size_t ObjectInterfaceCounter;
00247 };
00248
00249 std::size_t PluginInterface::ObjectInterfaceCounter = 0;
00250
00261 template< class type1 > bool PluginInterface::InterfaceExported( nitro::DynamicLibLoader & Plugin )
00262 {
00263 void * ( * _GetInterface )( const char * , const char * );
00264
00265 try
00266 {
00267 if( Plugin.ResourceExists( "GetInterface" ) == false )
00268 {
00269 throw( nitro::exception( "Loaded module is not a plugin" , 1 ) );
00270 }
00271
00272 _GetInterface = ( void * ( * )( const char * , const char * ) )Plugin.GetResource( "GetInterface" );
00273 }
00274 catch( nitro::exception e )
00275 {
00276 throw( nitro::exception( std::string( "PluginInterface::InterfaceExported( nitro::DynamicLibLoader & Plugin )::" ) + e.what() , e.code() ) );
00277 }
00278 catch( ... )
00279 {
00280 throw( nitro::exception( std::string( "PluginInterface::InterfaceExported( nitro::DynamicLibLoader & Plugin )::An error occured" ) , 1 ) );
00281 }
00282
00283 try
00284 {
00285 _GetInterface( typeid( type1 ).name() , "" );
00286
00287 return( true );
00288 }
00289 catch( ... )
00290 {
00291 return( false );
00292 }
00293 }
00294
00305 template< class type1 > type1 * PluginInterface::GetInterface( nitro::DynamicLibLoader & Plugin , const std::string & ObjectName = "" )
00306 {
00307 try
00308 {
00309 if( Plugin.ResourceExists( "GetInterface" ) == false )
00310 {
00311 throw( nitro::exception( "Loaded module is not a plugin" , 1 ) );
00312 }
00313
00314 void * ( * _GetInterface )( const char * , const char * );
00315 _GetInterface = ( void * ( * )( const char * , const char * ) )Plugin.GetResource( "GetInterface" );
00316
00317 return( ( type1 * )_GetInterface( typeid( type1 ).name() , ObjectName.c_str() ) );
00318 }
00319 catch( nitro::exception e )
00320 {
00321 throw( nitro::exception( std::string( "PluginInterface::GetInterface( nitro::DynamicLibLoader & Plugin , const std::string & ObjectName )::" ) + e.what() , e.code() ) );
00322 }
00323 catch( ... )
00324 {
00325 throw( nitro::exception( std::string( "PluginInterface::GetInterface( nitro::DynamicLibLoader & Plugin , const std::string & ObjectName )::An error occured" ) , 1 ) );
00326 }
00327 }
00328
00339 template< class type1 > type1 * PluginInterface::GetNewInterface( nitro::DynamicLibLoader & Plugin )
00340 {
00341 try
00342 {
00343 if( Plugin.ResourceExists( "GetInterface" ) == false )
00344 {
00345 throw( nitro::exception( "Loaded module is not a plugin" , 1 ) );
00346 }
00347
00348 void * ( * _GetInterface )( const char * , const char * );
00349 _GetInterface = ( void * ( * )( const char * , const char * ) )Plugin.GetResource( "GetInterface" );
00350
00351 std::size_t CurrentCursor( PluginInterface::ObjectInterfaceCounter++ );
00352 std::string ObjectInterfaceCursor( nitro::Convertes::itoa( CurrentCursor ) );
00353 std::string ObjectName( "" );
00354 ObjectName += "_new_interface[";
00355 ObjectName += ObjectInterfaceCursor;
00356 ObjectName += "]";
00357
00358 return( ( type1 * )_GetInterface( typeid( type1 ).name() , ObjectName.c_str() ) );
00359 }
00360 catch( nitro::exception e )
00361 {
00362 throw( nitro::exception( std::string( "PluginInterface::GetNewInterface( nitro::DynamicLibLoader & Plugin )::" ) + e.what() , e.code() ) );
00363 }
00364 catch( ... )
00365 {
00366 throw( nitro::exception( std::string( "PluginInterface::GetNewInterface( nitro::DynamicLibLoader & Plugin )::An error occured" ) , 1 ) );
00367 }
00368 }
00369
00380 template< class type1 > void PluginInterface::ReleaseInterface( nitro::DynamicLibLoader & Plugin , type1 * Interface )
00381 {
00382 try
00383 {
00384 if( Plugin.ResourceExists( "ReleaseInterface" ) == false )
00385 {
00386 throw( nitro::exception( "Loaded module is not a plugin" , 1 ) );
00387 }
00388
00389 void ( * _ReleaseInterface )( void * );
00390 _ReleaseInterface = ( void ( * )( void * ) )Plugin.GetResource( "ReleaseInterface" );
00391
00392 _ReleaseInterface( ( void * ) Interface );
00393 }
00394 catch( nitro::exception e )
00395 {
00396 throw( nitro::exception( std::string( "PluginInterface::ReleaseInterface( nitro::DynamicLibLoader & Plugin , type1 * Interface )::" ) + e.what() , e.code() ) );
00397 }
00398 catch( ... )
00399 {
00400 throw( nitro::exception( std::string( "PluginInterface::ReleaseInterface( nitro::DynamicLibLoader & Plugin , type1 * Interface )::An error occured" ) , 1 ) );
00401 }
00402 }
00403 }
00404
00405 #endif