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/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 )
24 std::vector< std::string > libs;
25 cpPlugins::TokenizeString( libs, cpPlugins_DynLibs, ";" );
26 this->_AddInstancesLib( libs, cpPlugins_CompilationDir );
27 this->_AddInstancesLib( libs, cpPlugins_InstallationDir );
29 for( auto l = libs.begin( ); l != libs.end( ); ++l )
31 std::string error = "";
32 void* hnd = Self::_DLOpen( *l, error );
33 if( hnd == NULL || error != "" )
34 throw std::runtime_error(
35 std::string( "cpPlugins::Interface: Could not load library \"" ) +
37 std::string( "\": " ) +
44 Self::InterfacesCount++;
47 // -------------------------------------------------------------------------
48 cpPlugins::Interface::
52 Self::InterfacesCount--;
53 if( Self::InterfacesCount == 0 )
55 // TODO: unload vtk and itk
60 // -------------------------------------------------------------------------
61 const cpPlugins::Interface::
62 TFilters& cpPlugins::Interface::
65 return( this->m_Filters );
68 // -------------------------------------------------------------------------
69 void cpPlugins::Interface::
72 // Load environment configuration
73 this->m_Paths.clear( );
74 char* p = std::getenv( cpPlugins_PATHS );
76 cpPlugins::TokenizeString( this->m_Paths, p, cpPlugins_SEPARATOR );
77 this->m_Paths.push_back( "." );
80 // -------------------------------------------------------------------------
81 void cpPlugins::Interface::
82 GuessAccesiblePlugins( )
84 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
85 try { this->LoadPluginDir( *i ); } catch( ... ) { }
88 // -------------------------------------------------------------------------
89 void cpPlugins::Interface::
90 LoadPlugin( const std::string& name )
92 std::stringstream str;
93 str << cpPlugins_LIB_PREFIX << name << "." << cpPlugins_LIB_EXT;
94 std::string base_name = str.str( );
96 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
98 std::string filename = *i;
99 if( i->back( ) != '/' )
100 filename += std::string( "/" );
101 filename += base_name;
104 this->LoadPluginFile( filename );
113 throw std::runtime_error(
114 std::string( "cpPlugins::Interface: Plugins library \"" ) +
116 std::string( "\" not found." )
120 // -------------------------------------------------------------------------
121 void cpPlugins::Interface::
122 LoadPluginDir( const std::string& dirname )
126 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
128 while( ( ent = readdir( dir ) ) != NULL )
132 this->LoadPluginFile(
144 throw std::runtime_error(
145 std::string( "cpPlugins::Interface: Could not load directory " ) +
146 std::string( "\"" ) + dirname + std::string( "\"" )
150 // -------------------------------------------------------------------------
151 void cpPlugins::Interface::
152 LoadPluginFile( const std::string& filename )
154 // Canonical filename
155 auto canonical = cpPlugins::CanonicalPath( filename );
156 if( canonical == "" )
157 throw std::runtime_error(
158 std::string( "cpPlugins::Interface: Library \"" ) +
160 std::string( "\" does not exist." )
163 // Try to load the library
165 void* hnd = Self::_DLOpen( canonical, error );
166 if( hnd == NULL || error != "" )
167 throw std::runtime_error(
168 std::string( "cpPlugins::Interface: Could not load library \"" ) +
170 std::string( "\": " ) +
175 std::string pl_name = Self::_DLGetName( hnd );
177 // Check if it was already loaded
178 if( this->m_DynLibraries.find( pl_name ) != this->m_DynLibraries.end( ) )
182 TFilters filters = Self::_DLGetFilters( hnd );
184 // Save the loaded filters info
185 bool save_handler = false;
186 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
188 // Check if the filter is completely new
189 auto act_catIt = this->m_Filters.find( catIt->first );
191 auto clsIt = catIt->second.begin( );
192 clsIt != catIt->second.end( );
196 bool new_filter = true;
197 if( act_catIt != this->m_Filters.end( ) )
199 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
204 // Update filters container
205 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
206 if( creator != NULL )
208 this->m_DynFilters[ catIt->first][ *clsIt ] =
209 TDynFunc( pl_name, creator );
210 this->m_Filters[ catIt->first ].insert( *clsIt );
221 // Keep dynlib handler, if needed
223 this->m_DynLibraries[ pl_name ] = TDynFileInfo( canonical, hnd );
225 Self::_DLClose( hnd );
228 // -------------------------------------------------------------------------
229 void cpPlugins::Interface::
233 auto d = this->m_DynLibraries.begin( );
234 d != this->m_DynLibraries.end( );
237 Self::_DLClose( d->second.second );
238 this->m_DynLibraries.clear( );
239 this->m_DynFilters.clear( );
240 this->m_Filters.clear( );
243 // -------------------------------------------------------------------------
244 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
245 Create( const std::string& category, const std::string& name )
247 typedef cpPlugins::ProcessObject::Pointer _TPointer;
248 _TPointer filter = NULL;
249 auto catIt = this->m_DynFilters.find( category );
250 if( catIt != this->m_DynFilters.end( ) )
252 auto clsIt = catIt->second.find( name );
253 if( clsIt != catIt->second.end( ) )
255 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
262 // -------------------------------------------------------------------------
263 std::string cpPlugins::Interface::
264 GetPluginName( const std::string& category, const std::string& name ) const
266 std::string plugin = "";
267 auto catIt = this->m_DynFilters.find( category );
268 if( catIt != this->m_DynFilters.end( ) )
270 auto clsIt = catIt->second.find( name );
271 if( clsIt != catIt->second.end( ) )
272 plugin = clsIt->second.first;
278 // -------------------------------------------------------------------------
279 std::string cpPlugins::Interface::
280 GetPluginName( const ProcessObject* obj ) const
285 obj->GetClassCategory( ),
293 // -------------------------------------------------------------------------
294 std::set< std::string > cpPlugins::Interface::
297 std::set< std::string > res;
298 auto i = this->m_DynLibraries.begin( );
299 for( ; i != this->m_DynLibraries.end( ); ++i )
300 res.insert( i->first );
304 // -------------------------------------------------------------------------
305 template< class _TList >
306 void cpPlugins::Interface::
307 _AddInstancesLib( _TList& libs, const std::string& path )
311 if( ( dir = opendir( path.c_str( ) ) ) != NULL )
313 while( ( ent = readdir( dir ) ) != NULL )
315 std::string fname = path + std::string( "/" ) + ent->d_name;
316 if( fname.find( "cpPlugins_Instances_" ) != std::string::npos )
317 libs.push_back( fname );
325 // -------------------------------------------------------------------------
326 void* cpPlugins::Interface::
327 _DLOpen( const std::string& fname, std::string& error )
330 #ifdef cpPlugins_SYS_WINDOWS
331 hnd = ::LoadLibraryA( fname.c_str( ) );
332 #else // cpPlugins_SYS_WINDOWS
333 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
338 #endif // cpPlugins_SYS_WINDOWS
342 // -------------------------------------------------------------------------
343 const char* cpPlugins::Interface::
344 _DLGetName( void* hnd )
347 typedef const char* ( *f_t )( );
349 #ifdef cpPlugins_SYS_WINDOWS
350 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_Name" ) );
351 #else // cpPlugins_SYS_WINDOWS
352 f = ( f_t )( dlsym( hnd, "cpPlugins_Name" ) );
353 #endif // cpPlugins_SYS_WINDOWS
356 Self::_DLClose( hnd );
357 throw std::runtime_error(
358 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
365 // -------------------------------------------------------------------------
366 cpPlugins::Interface::
367 TFilters cpPlugins::Interface::
368 _DLGetFilters( void* hnd )
371 typedef const char* ( *f_t )( );
373 #ifdef cpPlugins_SYS_WINDOWS
374 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
375 #else // cpPlugins_SYS_WINDOWS
376 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
377 #endif // cpPlugins_SYS_WINDOWS
380 Self::_DLClose( hnd );
381 throw std::runtime_error(
382 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
386 std::string descriptors = f( );
388 // Demangle descriptors
390 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
391 std::istringstream str( descriptors );
394 std::string value, category, name;
398 std::replace( value.begin( ), value.end( ), ':', ' ' );
399 std::istringstream value_str( value );
400 value_str >> category >> name;
401 filters[ category ].insert( name );
407 // -------------------------------------------------------------------------
408 cpPlugins::Interface::
409 TCreator cpPlugins::Interface::
411 void* hnd, const std::string& category, const std::string& name
415 std::string func_name = category + "_" + name;
416 #ifdef cpPlugins_SYS_WINDOWS
417 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
418 #else // cpPlugins_SYS_WINDOWS
419 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
420 #endif // cpPlugins_SYS_WINDOWS
422 throw std::runtime_error(
423 std::string( "cpPlugins::Interface: Class \"" ) +
424 category + std::string( ":" ) + name +
425 std::string( "\" does not have a valid creator function." )
430 // -------------------------------------------------------------------------
431 void cpPlugins::Interface::
432 _DLClose( void* hnd )
434 #ifdef cpPlugins_SYS_WINDOWS
435 ::FreeLibrary( ( HMODULE )hnd );
436 #else // cpPlugins_SYS_WINDOWS
438 #endif // cpPlugins_SYS_WINDOWS