1 #include <cpPlugins/Interface.h>
3 #ifdef cpPlugins_SYS_WINDOWS
5 #else // cpPlugins_SYS_WINDOWS
7 #endif // cpPlugins_SYS_WINDOWS
8 #include <cpPlugins_dirent.h>
10 // -------------------------------------------------------------------------
11 cpPlugins::Interface::
16 // -------------------------------------------------------------------------
17 cpPlugins::Interface::
23 // -------------------------------------------------------------------------
24 const cpPlugins::Interface::
25 TFilters& cpPlugins::Interface::
28 return( this->m_Filters );
31 // -------------------------------------------------------------------------
32 void cpPlugins::Interface::
33 GuessAccesiblePlugins( )
35 // Load environment configuration
36 char* path = std::getenv( "cpPlugins_PATHS" );
39 std::vector< std::string > tokens;
40 cpPlugins::TokenizeString( tokens, path, "#" );
41 for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt )
42 try { this->LoadPluginDir( *tIt ); } catch( ... ) { }
47 auto lpath = cpPlugins::CanonicalPath( "." );
48 try { this->LoadPluginDir( lpath ); } catch( ... ) { }
51 // -------------------------------------------------------------------------
52 bool cpPlugins::Interface::
53 LoadConfiguration( const std::string& filename )
55 std::ifstream in( filename.c_str( ) );
61 while( std::getline( in, line ) )
62 try { this->LoadPluginFile( line ); } catch( ... ) { }
66 // -------------------------------------------------------------------------
67 bool cpPlugins::Interface::
68 SaveConfiguration( const std::string& filename ) const
70 std::ofstream out( filename.c_str( ) );
73 auto dIt = this->m_DynLibraries.begin( );
74 for( ; dIt != this->m_DynLibraries.end( ); ++dIt )
75 out << dIt->first << std::endl;
80 // -------------------------------------------------------------------------
81 void cpPlugins::Interface::
82 LoadPluginFile( const std::string& filename )
84 // Open library with its canonical path name
85 auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
86 if( canonical_fn == "" )
87 throw std::runtime_error(
88 std::string( "cpPlugins::Interface: Library \"" ) +
90 std::string( "\" does not exist." )
93 // Check if it was already loaded
95 this->m_DynLibraries.find( canonical_fn ) != this->m_DynLibraries.end( )
99 // Ok, try to load the library
100 void* hnd = Self::_DLOpen( canonical_fn );
102 throw std::runtime_error(
103 std::string( "cpPlugins::Interface: Could not load library \"" ) +
109 TFilters filters = Self::_DLGetFilters( hnd );
111 // Save the loaded filters info
112 bool save_handler = false;
113 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
115 // Check if the filter is completely new
116 auto act_catIt = this->m_Filters.find( catIt->first );
118 auto clsIt = catIt->second.begin( );
119 clsIt != catIt->second.end( );
123 bool new_filter = true;
124 if( act_catIt != this->m_Filters.end( ) )
126 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
131 // Update filters container
132 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
133 if( creator != NULL )
135 this->m_DynFilters[ catIt->first][ *clsIt ] =
136 TDynFunc( canonical_fn, creator );
137 this->m_Filters[ catIt->first ].insert( *clsIt );
148 // Keep dynlib handler, if needed
150 this->m_DynLibraries[ canonical_fn ] = hnd;
152 Self::_DLClose( hnd );
155 // -------------------------------------------------------------------------
156 unsigned int cpPlugins::Interface::
157 LoadPluginDir( const std::string& dirname )
161 unsigned int count = 0;
162 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
164 while( ( ent = readdir( dir ) ) != NULL )
168 this->LoadPluginFile(
181 throw std::runtime_error(
182 std::string( "cpPlugins::Interface: Could not load directory " ) +
183 std::string( "\"" ) + dirname + std::string( "\"" )
188 // -------------------------------------------------------------------------
189 void cpPlugins::Interface::
193 auto d = this->m_DynLibraries.begin( );
194 d != this->m_DynLibraries.end( );
197 Self::_DLClose( d->second );
198 this->m_DynLibraries.clear( );
199 this->m_DynFilters.clear( );
200 this->m_Filters.clear( );
203 // -------------------------------------------------------------------------
204 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
205 Create( const std::string& category, const std::string& name )
207 typedef cpPlugins::ProcessObject::Pointer _TPointer;
208 _TPointer filter = NULL;
209 auto catIt = this->m_DynFilters.find( category );
210 if( catIt != this->m_DynFilters.end( ) )
212 auto clsIt = catIt->second.find( name );
213 if( clsIt != catIt->second.end( ) )
215 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
222 // -------------------------------------------------------------------------
223 void* cpPlugins::Interface::
224 _DLOpen( const std::string& fname )
227 #ifdef cpPlugins_SYS_WINDOWS
228 hnd = ::LoadLibraryA( fname.c_str( ) );
229 #else // cpPlugins_SYS_WINDOWS
230 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
232 #endif // cpPlugins_SYS_WINDOWS
236 // -------------------------------------------------------------------------
237 cpPlugins::Interface::
238 TFilters cpPlugins::Interface::
239 _DLGetFilters( void* hnd )
242 typedef const char* ( *f_t )( );
244 #ifdef cpPlugins_SYS_WINDOWS
245 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
246 #else // cpPlugins_SYS_WINDOWS
247 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
248 #endif // cpPlugins_SYS_WINDOWS
251 Self::_DLClose( hnd );
252 throw std::runtime_error(
253 "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
257 std::string descriptors = f( );
259 // Demangle descriptors
261 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
262 std::istringstream str( descriptors );
265 std::string value, category, name;
269 std::replace( value.begin( ), value.end( ), ':', ' ' );
270 std::istringstream value_str( value );
271 value_str >> category >> name;
272 filters[ category ].insert( name );
278 // -------------------------------------------------------------------------
279 cpPlugins::Interface::
280 TCreator cpPlugins::Interface::
282 void* hnd, const std::string& category, const std::string& name
286 std::string func_name = category + "_" + name;
287 #ifdef cpPlugins_SYS_WINDOWS
288 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
289 #else // cpPlugins_SYS_WINDOWS
290 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
291 #endif // cpPlugins_SYS_WINDOWS
293 throw std::runtime_error(
294 std::string( "cpPlugins::Interface: Class \"" ) +
295 category + std::string( ":" ) + name +
296 std::string( "\" does not have a valid creator function." )
301 // -------------------------------------------------------------------------
302 void cpPlugins::Interface::
303 _DLClose( void* hnd )
305 #ifdef cpPlugins_SYS_WINDOWS
306 ::FreeLibrary( ( HMODULE )hnd );
307 #else // cpPlugins_SYS_WINDOWS
309 #endif // cpPlugins_SYS_WINDOWS