#include #ifdef cpPlugins_SYS_WINDOWS # include #else // cpPlugins_SYS_WINDOWS # include #endif // cpPlugins_SYS_WINDOWS // ------------------------------------------------------------------------- cpPlugins::Interface:: Interface( ) { } // ------------------------------------------------------------------------- cpPlugins::Interface:: ~Interface( ) { this->UnloadAll( ); } // ------------------------------------------------------------------------- const cpPlugins::Interface:: TFilters& cpPlugins::Interface:: 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( ); return( true ); } // ------------------------------------------------------------------------- void cpPlugins::Interface:: LoadPluginFile( const std::string& filename ) { // Open library with its canonical path name auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename ); if( canonical_fn == "" ) throw std::runtime_error( std::string( "cpPlugins::Interface: Library \"" ) + filename + std::string( "\" does not exist." ) ); void* hnd = Self::_DLOpen( canonical_fn ); if( hnd == NULL ) throw std::runtime_error( std::string( "cpPlugins::Interface: Could not load library \"" ) + filename + std::string( "\"" ) ); // Load filters TFilters filters = Self::_DLGetFilters( hnd ); // Save the loaded filters info bool save_handler = false; for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt ) { // 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 ) { 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 ) { // Update filters container auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt ); if( creator != NULL ) { this->m_DynFilters[ catIt->first][ *clsIt ] = TDynFunc( canonical_fn, creator ); this->m_Filters[ catIt->first ].insert( *clsIt ); save_handler = true; } // fi } // fi } // rof } // rof // Keep dynlib handler, if needed if( save_handler ) this->m_DynLibraries[ canonical_fn ] = hnd; else Self::_DLClose( hnd ); } // ------------------------------------------------------------------------- void cpPlugins::Interface:: UnloadAll( ) { 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( ); } // ------------------------------------------------------------------------- cpPlugins::ProcessObject::Pointer cpPlugins::Interface:: Create( const std::string& category, const std::string& name ) { typedef cpPlugins::ProcessObject::Pointer _TPointer; _TPointer filter = NULL; auto catIt = this->m_DynFilters.find( category ); if( catIt != this->m_DynFilters.end( ) ) { auto clsIt = catIt->second.find( name ); if( clsIt != catIt->second.end( ) ) filter = ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )-> GetPointer( ); } // 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 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL ); dlerror( ); #endif // cpPlugins_SYS_WINDOWS return( hnd ); } // ------------------------------------------------------------------------- cpPlugins::Interface:: TFilters cpPlugins::Interface:: _DLGetFilters( void* hnd ) { // Get descriptors typedef const char* ( *f_t )( ); f_t f = NULL; #ifdef cpPlugins_SYS_WINDOWS f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) ); #else // cpPlugins_SYS_WINDOWS f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) ); #endif // cpPlugins_SYS_WINDOWS if( f == NULL ) { Self::_DLClose( hnd ); throw std::runtime_error( "cpPlugins::Interface: Library not recognized as a cpPlugins library: " ); } // fi std::string descriptors = f( ); // Demangle descriptors TFilters filters; std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' ); std::istringstream str( descriptors ); while( str ) { std::string value, category, name; str >> value; if( value == "" ) continue; std::replace( value.begin( ), value.end( ), ':', ' ' ); std::istringstream value_str( value ); value_str >> category >> name; filters[ category ].insert( name ); } // elihw 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 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) ); #else // cpPlugins_SYS_WINDOWS c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) ); #endif // cpPlugins_SYS_WINDOWS 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." ) ); 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$