X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=lib%2FcpPlugins%2FInterface.cxx;h=259288243d5a309e803115bddb6e50a98645b210;hb=f533290f40279617e54e19086dde7c0ba9b07f5b;hp=de6d63116e6c0b2b35bf58c1c4f9d0ba2bf72de5;hpb=1b0022070ff3b5f80f6f8c8b87f73032f5685eaf;p=cpPlugins.git diff --git a/lib/cpPlugins/Interface.cxx b/lib/cpPlugins/Interface.cxx index de6d631..2592882 100644 --- a/lib/cpPlugins/Interface.cxx +++ b/lib/cpPlugins/Interface.cxx @@ -1,15 +1,11 @@ #include -#include -#include -#include - #ifdef cpPlugins_SYS_WINDOWS +# include #else // cpPlugins_SYS_WINDOWS # include #endif // cpPlugins_SYS_WINDOWS - // ------------------------------------------------------------------------- cpPlugins::Interface:: Interface( ) @@ -31,88 +27,118 @@ GetFilters( ) return( this->m_Filters ); } +// ------------------------------------------------------------------------- +bool cpPlugins::Interface:: +LoadConfiguration( const std::string& filename ) +{ + std::ifstream in( filename.c_str( ) ); + if( !in ) + return( false ); + + this->UnloadAll( ); + std::string line; + while( std::getline( in, line ) ) + { + try + { + this->LoadPluginFile( line ); + } + catch( ... ) + { + // Do nothing + + } // yrt + + } // elihw + return( true ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Interface:: +SaveConfiguration( const std::string& filename ) const +{ + std::ofstream out( filename.c_str( ) ); + if( !out ) + return( false ); + auto dIt = this->m_DynLibraries.begin( ); + for( ; dIt != this->m_DynLibraries.end( ); ++dIt ) + out << dIt->first << std::endl; + out.close( ); +} + // ------------------------------------------------------------------------- void cpPlugins::Interface:: LoadPluginFile( const std::string& filename ) { + // Open library with its canonical path name auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename ); - void* hnd = NULL; - std::map< std::string, std::set< std::string > > filters; -#ifdef cpPlugins_SYS_WINDOWS - // TODO: -#else // cpPlugins_SYS_WINDOWS - - // Try to load canonical filename and clean error messages - hnd = dlopen( canonical_fn.c_str( ), RTLD_NOW | RTLD_GLOBAL ); + void* hnd = Self::_DLOpen( canonical_fn ); if( hnd == NULL ) throw std::runtime_error( std::string( "cpPlugins::Interface: Could not load library \"" ) + canonical_fn + std::string( "\"" ) ); - dlerror( ); - // Init plugins - typedef const std::map< std::string, std::set< std::string > > ( *func_t )( ); - auto func = ( func_t ) dlsym( hnd, "LoadedFilters" ); - const char* func_error = dlerror( ); - if( func_error != NULL ) - { - dlclose( hnd ); - throw std::runtime_error( - std::string( "cpPlugins::Interface: Library \"" ) + - canonical_fn + - std::string( "\" not recognized as a cpPlugins library." ) - ); + // Load filters + TFilters filters = Self::_DLGetFilters( hnd ); - } // fi - filters = func( ); -#endif // cpPlugins_SYS_WINDOWS - if( hnd != NULL ) + // Save the loaded filters info + bool save_handler = false; + for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt ) { - // Save the loaded filters names - for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt ) + // Check if the filter is completely new + auto act_catIt = this->m_Filters.find( catIt->first ); + for( + auto clsIt = catIt->second.begin( ); + clsIt != catIt->second.end( ); + ++clsIt + ) { - auto colIt = this->m_Filters.find( cIt->first ); - for( auto fIt = cIt->second.begin( ); fIt != cIt->second.end( ); ++fIt ) + bool new_filter = true; + if( act_catIt != this->m_Filters.end( ) ) + new_filter = + ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) ); + + // Ok, it is new + if( new_filter ) { - bool found = false; - if( colIt != this->m_Filters.end( ) ) + // Update filters container + TCreator creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt ); + if( creator != NULL ) { - auto rowIt = colIt->second.find( *fIt ); - if( rowIt != colIt->second.end( ) ) - found = true; + this->m_DynFilters[ catIt->first][ *clsIt ] = + TDynFunc( canonical_fn, creator ); + this->m_Filters[ catIt->first ].insert( *clsIt ); + save_handler = true; } // fi - if( !found ) - this->m_Filters[ cIt->first ][ *fIt ] = canonical_fn; - } // rof + } // fi } // rof - // Save the hnd - this->m_Plugins[ canonical_fn ] = hnd; - } + } // rof + + // Keep dynlib handler, if needed + if( save_handler ) + this->m_DynLibraries[ canonical_fn ] = hnd; else - throw std::runtime_error( - "cpPlugins::Interface: Operative system not yet supported." - ); + Self::_DLClose( hnd ); } // ------------------------------------------------------------------------- void cpPlugins::Interface:: UnloadAll( ) { - auto pIt = this->m_Plugins.begin( ); - for( ; pIt != this->m_Plugins.end( ); ++pIt ) - { -#ifdef cpPlugins_SYS_WINDOWS -#else // cpPlugins_SYS_WINDOWS - dlclose( pIt->second ); -#endif // cpPlugins_SYS_WINDOWS - } // rof - this->m_Plugins.clear( ); + for( + auto d = this->m_DynLibraries.begin( ); + d != this->m_DynLibraries.end( ); + ++d + ) + Self::_DLClose( d->second ); + this->m_DynLibraries.clear( ); + this->m_DynFilters.clear( ); this->m_Filters.clear( ); } @@ -120,38 +146,95 @@ UnloadAll( ) cpPlugins::ProcessObject::Pointer cpPlugins::Interface:: Create( const std::string& category, const std::string& name ) { - cpPlugins::ProcessObject::Pointer filter; - auto cIt = this->m_Filters.find( category ); - if( cIt != this->m_Filters.end( ) ) + cpPlugins::ProcessObject::Pointer filter = NULL; + auto catIt = this->m_DynFilters.find( category ); + if( catIt != this->m_DynFilters.end( ) ) { - auto nIt = cIt->second.find( name ); - if( nIt != cIt->second.end( ) ) - { - auto pIt = this->m_Plugins.find( nIt->second ); - if( pIt != this->m_Plugins.end( ) ) - { + auto clsIt = catIt->second.find( name ); + if( clsIt != catIt->second.end( ) ) + filter = clsIt->second.second( ); + + } // fi + return( filter ); +} + +// ------------------------------------------------------------------------- +void* cpPlugins::Interface:: +_DLOpen( const std::string& fname ) +{ + void* hnd = NULL; #ifdef cpPlugins_SYS_WINDOWS + hnd = ::LoadLibraryA( fname.c_str( ) ); #else // cpPlugins_SYS_WINDOWS - std::string func_name = category + "_" + name; - typedef cpPlugins::ProcessObject::Pointer ( *func_t )( ); - auto func = ( func_t ) dlsym( pIt->second, func_name.c_str( ) ); - if( func == NULL ) - { - throw std::runtime_error( - std::string( "cpPlugins::Interface: Class \"" ) + - category + std::string( ":" ) + name + - std::string( "\" does not have a valid creator function." ) - ); - - } // fi - filter = func( ); + hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL ); + dlerror( ); #endif // cpPlugins_SYS_WINDOWS - } // fi + return( hnd ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +TFilters cpPlugins::Interface:: +_DLGetFilters( void* hnd ) +{ + typedef const TFilters ( *f_t )( ); - } // fi + TFilters filters; +#ifdef cpPlugins_SYS_WINDOWS + auto f = ( f_t )( + ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) + ); + std::cout << f << std::endl; +#else // cpPlugins_SYS_WINDOWS + auto f = ( f_t ) dlsym( hnd, "cpPlugins_LoadedFilters" ); + const char* err = dlerror( ); + if( err != NULL ) + { + dlclose( hnd ); + throw std::runtime_error( + std::string( + "cpPlugins::Interface: Library not recognized as a cpPlugins library: " + ) + std::string( err ) + ); } // fi - return( filter ); +#endif // cpPlugins_SYS_WINDOWS + filters = f( ); + return( filters ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +TCreator cpPlugins::Interface:: +_DLGetCreator( + void* hnd, const std::string& category, const std::string& name + ) +{ + TCreator c = NULL; + std::string func_name = category + "_" + name; +#ifdef cpPlugins_SYS_WINDOWS + // TODO: +#else // cpPlugins_SYS_WINDOWS + c = ( TCreator )dlsym( hnd, func_name.c_str( ) ); + if( c == NULL ) + throw std::runtime_error( + std::string( "cpPlugins::Interface: Class \"" ) + + category + std::string( ":" ) + name + + std::string( "\" does not have a valid creator function." ) + ); +#endif // cpPlugins_SYS_WINDOWS + return( c ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +_DLClose( void* hnd ) +{ +#ifdef cpPlugins_SYS_WINDOWS + ::FreeLibrary( ( HMODULE )hnd ); +#else // cpPlugins_SYS_WINDOWS + dlclose( hnd ); +#endif // cpPlugins_SYS_WINDOWS } // eof - $RCSfile$