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>
9 #include <cpPlugins_Instances/cpPlugins_DynLibs.h>
12 // -------------------------------------------------------------------------
13 unsigned int cpPlugins::Interface::InterfacesCount = 0;
15 // -------------------------------------------------------------------------
16 cpPlugins::Interface::
21 // Explicitly load all ITK and VTK
22 if( Self::InterfacesCount == 0 )
25 std::vector< std::string > libs;
26 cpPlugins::TokenizeString( libs, cpPlugins_DynLibs, ";" );
29 for( auto p = this->m_Paths.begin( ); p != this->m_Paths.end( ); ++p )
33 if( ( dir = opendir( p->c_str( ) ) ) != NULL )
35 while( ( ent = readdir( dir ) ) != NULL )
37 std::string fname = *p + std::string( "/" ) + ent->d_name;
39 fname.find( "_Instances" ) != std::string::npos ||
40 fname.find( "cpExtensions" ) != std::string::npos
42 libs.push_back( fname );
51 for( auto l = libs.begin( ); l != libs.end( ); ++l )
53 std::string error = "";
54 void* hnd = Self::_DLOpen( *l, error );
55 if( hnd == NULL || error != "" )
56 throw std::runtime_error(
57 std::string( "cpPlugins::Interface: Could not load library \"" ) +
59 std::string( "\": " ) +
66 Self::InterfacesCount++;
69 // -------------------------------------------------------------------------
70 cpPlugins::Interface::
74 Self::InterfacesCount--;
75 if( Self::InterfacesCount == 0 )
77 // TODO: unload vtk and itk
82 // -------------------------------------------------------------------------
83 const cpPlugins::Interface::
84 TFilters& cpPlugins::Interface::
87 return( this->m_Filters );
90 // -------------------------------------------------------------------------
91 void cpPlugins::Interface::
94 // Load environment configuration
95 this->m_Paths.clear( );
96 char* p = std::getenv( cpPlugins_PATHS );
98 cpPlugins::TokenizeString( this->m_Paths, p, cpPlugins_SEPARATOR );
99 this->m_Paths.push_back( "." );
102 // -------------------------------------------------------------------------
103 void cpPlugins::Interface::
104 GuessAccesiblePlugins( )
106 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
107 try { this->LoadPluginDir( *i ); } catch( ... ) { }
110 // -------------------------------------------------------------------------
111 void cpPlugins::Interface::
112 LoadPlugin( const std::string& name )
114 std::stringstream str;
115 str << cpPlugins_LIB_PREFIX << name << "." << cpPlugins_LIB_EXT;
116 std::string base_name = str.str( );
118 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
120 std::string filename = *i;
121 if( i->back( ) != '/' )
122 filename += std::string( "/" );
123 filename += base_name;
126 this->LoadPluginFile( filename );
135 throw std::runtime_error(
136 std::string( "cpPlugins::Interface: Plugins library \"" ) +
138 std::string( "\" not found." )
142 // -------------------------------------------------------------------------
143 void cpPlugins::Interface::
144 LoadPluginDir( const std::string& dirname )
148 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
150 while( ( ent = readdir( dir ) ) != NULL )
154 this->LoadPluginFile(
166 throw std::runtime_error(
167 std::string( "cpPlugins::Interface: Could not load directory " ) +
168 std::string( "\"" ) + dirname + std::string( "\"" )
172 // -------------------------------------------------------------------------
173 void cpPlugins::Interface::
174 LoadPluginFile( const std::string& filename )
176 // Canonical filename
177 auto canonical = cpPlugins::CanonicalPath( filename );
178 if( canonical == "" )
179 throw std::runtime_error(
180 std::string( "cpPlugins::Interface: Library \"" ) +
182 std::string( "\" does not exist." )
185 // Try to load the library
187 void* hnd = Self::_DLOpen( canonical, error );
188 if( hnd == NULL || error != "" )
189 throw std::runtime_error(
190 std::string( "cpPlugins::Interface: Could not load library \"" ) +
192 std::string( "\": " ) +
197 std::string pl_name = Self::_DLGetName( hnd );
199 // Check if it was already loaded
200 if( this->m_DynLibraries.find( pl_name ) != this->m_DynLibraries.end( ) )
204 TFilters filters = Self::_DLGetFilters( hnd );
206 // Save the loaded filters info
207 bool save_handler = false;
208 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
210 // Check if the filter is completely new
211 auto act_catIt = this->m_Filters.find( catIt->first );
213 auto clsIt = catIt->second.begin( );
214 clsIt != catIt->second.end( );
218 bool new_filter = true;
219 if( act_catIt != this->m_Filters.end( ) )
221 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
226 // Update filters container
227 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
228 if( creator != NULL )
230 this->m_DynFilters[ catIt->first][ *clsIt ] =
231 TDynFunc( pl_name, creator );
232 this->m_Filters[ catIt->first ].insert( *clsIt );
243 // Keep dynlib handler, if needed
245 this->m_DynLibraries[ pl_name ] = TDynFileInfo( canonical, hnd );
247 Self::_DLClose( hnd );
250 // -------------------------------------------------------------------------
251 void cpPlugins::Interface::
255 auto d = this->m_DynLibraries.begin( );
256 d != this->m_DynLibraries.end( );
259 Self::_DLClose( d->second.second );
260 this->m_DynLibraries.clear( );
261 this->m_DynFilters.clear( );
262 this->m_Filters.clear( );
265 // -------------------------------------------------------------------------
266 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
267 Create( const std::string& category, const std::string& name )
269 typedef cpPlugins::ProcessObject::Pointer _TPointer;
270 _TPointer filter = NULL;
271 auto catIt = this->m_DynFilters.find( category );
272 if( catIt != this->m_DynFilters.end( ) )
274 auto clsIt = catIt->second.find( name );
275 if( clsIt != catIt->second.end( ) )
277 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
284 // -------------------------------------------------------------------------
285 std::string cpPlugins::Interface::
286 GetPluginName( const std::string& category, const std::string& name ) const
288 std::string plugin = "";
289 auto catIt = this->m_DynFilters.find( category );
290 if( catIt != this->m_DynFilters.end( ) )
292 auto clsIt = catIt->second.find( name );
293 if( clsIt != catIt->second.end( ) )
294 plugin = clsIt->second.first;
300 // -------------------------------------------------------------------------
301 std::string cpPlugins::Interface::
302 GetPluginName( const ProcessObject* obj ) const
307 obj->GetClassCategory( ),
315 // -------------------------------------------------------------------------
316 std::set< std::string > cpPlugins::Interface::
319 std::set< std::string > res;
320 auto i = this->m_DynLibraries.begin( );
321 for( ; i != this->m_DynLibraries.end( ); ++i )
322 res.insert( i->first );
326 // -------------------------------------------------------------------------
327 void* cpPlugins::Interface::
328 _DLOpen( const std::string& fname, std::string& error )
331 #ifdef cpPlugins_SYS_WINDOWS
332 hnd = ::LoadLibraryA( fname.c_str( ) );
333 #else // cpPlugins_SYS_WINDOWS
334 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
339 #endif // cpPlugins_SYS_WINDOWS
343 // -------------------------------------------------------------------------
344 const char* cpPlugins::Interface::
345 _DLGetName( void* hnd )
348 typedef const char* ( *f_t )( );
350 #ifdef cpPlugins_SYS_WINDOWS
351 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_Name" ) );
352 #else // cpPlugins_SYS_WINDOWS
353 f = ( f_t )( dlsym( hnd, "cpPlugins_Name" ) );
354 #endif // cpPlugins_SYS_WINDOWS
357 Self::_DLClose( hnd );
358 throw std::runtime_error(
359 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
366 // -------------------------------------------------------------------------
367 cpPlugins::Interface::
368 TFilters cpPlugins::Interface::
369 _DLGetFilters( void* hnd )
372 typedef const char* ( *f_t )( );
374 #ifdef cpPlugins_SYS_WINDOWS
375 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
376 #else // cpPlugins_SYS_WINDOWS
377 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
378 #endif // cpPlugins_SYS_WINDOWS
381 Self::_DLClose( hnd );
382 throw std::runtime_error(
383 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
387 std::string descriptors = f( );
389 // Demangle descriptors
391 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
392 std::istringstream str( descriptors );
395 std::string value, category, name;
399 std::replace( value.begin( ), value.end( ), ':', ' ' );
400 std::istringstream value_str( value );
401 value_str >> category >> name;
402 filters[ category ].insert( name );
408 // -------------------------------------------------------------------------
409 cpPlugins::Interface::
410 TCreator cpPlugins::Interface::
412 void* hnd, const std::string& category, const std::string& name
416 std::string func_name = category + "_" + name;
417 #ifdef cpPlugins_SYS_WINDOWS
418 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
419 #else // cpPlugins_SYS_WINDOWS
420 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
421 #endif // cpPlugins_SYS_WINDOWS
423 throw std::runtime_error(
424 std::string( "cpPlugins::Interface: Class \"" ) +
425 category + std::string( ":" ) + name +
426 std::string( "\" does not have a valid creator function." )
431 // -------------------------------------------------------------------------
432 void cpPlugins::Interface::
433 _DLClose( void* hnd )
435 #ifdef cpPlugins_SYS_WINDOWS
436 ::FreeLibrary( ( HMODULE )hnd );
437 #else // cpPlugins_SYS_WINDOWS
439 #endif // cpPlugins_SYS_WINDOWS