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;
38 if( fname.find( "_Instances" ) != std::string::npos )
39 libs.push_back( fname );
48 for( auto l = libs.begin( ); l != libs.end( ); ++l )
50 std::string error = "";
51 void* hnd = Self::_DLOpen( *l, error );
52 if( hnd == NULL || error != "" )
53 throw std::runtime_error(
54 std::string( "cpPlugins::Interface: Could not load library \"" ) +
56 std::string( "\": " ) +
63 Self::InterfacesCount++;
66 // -------------------------------------------------------------------------
67 cpPlugins::Interface::
71 Self::InterfacesCount--;
72 if( Self::InterfacesCount == 0 )
74 // TODO: unload vtk and itk
79 // -------------------------------------------------------------------------
80 const cpPlugins::Interface::
81 TFilters& cpPlugins::Interface::
84 return( this->m_Filters );
87 // -------------------------------------------------------------------------
88 void cpPlugins::Interface::
91 // Load environment configuration
92 this->m_Paths.clear( );
93 char* p = std::getenv( cpPlugins_PATHS );
95 cpPlugins::TokenizeString( this->m_Paths, p, cpPlugins_SEPARATOR );
96 this->m_Paths.push_back( "." );
99 // -------------------------------------------------------------------------
100 void cpPlugins::Interface::
101 GuessAccesiblePlugins( )
103 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
104 try { this->LoadPluginDir( *i ); } catch( ... ) { }
107 // -------------------------------------------------------------------------
108 void cpPlugins::Interface::
109 LoadPlugin( const std::string& name )
111 std::stringstream str;
112 str << cpPlugins_LIB_PREFIX << name << "." << cpPlugins_LIB_EXT;
113 std::string base_name = str.str( );
115 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
117 std::string filename = *i;
118 if( i->back( ) != '/' )
119 filename += std::string( "/" );
120 filename += base_name;
123 this->LoadPluginFile( filename );
132 throw std::runtime_error(
133 std::string( "cpPlugins::Interface: Plugins library \"" ) +
135 std::string( "\" not found." )
139 // -------------------------------------------------------------------------
140 void cpPlugins::Interface::
141 LoadPluginDir( const std::string& dirname )
145 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
147 while( ( ent = readdir( dir ) ) != NULL )
151 this->LoadPluginFile(
163 throw std::runtime_error(
164 std::string( "cpPlugins::Interface: Could not load directory " ) +
165 std::string( "\"" ) + dirname + std::string( "\"" )
169 // -------------------------------------------------------------------------
170 void cpPlugins::Interface::
171 LoadPluginFile( const std::string& filename )
173 // Canonical filename
174 auto canonical = cpPlugins::CanonicalPath( filename );
175 if( canonical == "" )
176 throw std::runtime_error(
177 std::string( "cpPlugins::Interface: Library \"" ) +
179 std::string( "\" does not exist." )
182 // Try to load the library
184 void* hnd = Self::_DLOpen( canonical, error );
185 if( hnd == NULL || error != "" )
186 throw std::runtime_error(
187 std::string( "cpPlugins::Interface: Could not load library \"" ) +
189 std::string( "\": " ) +
194 std::string pl_name = Self::_DLGetName( hnd );
196 // Check if it was already loaded
197 if( this->m_DynLibraries.find( pl_name ) != this->m_DynLibraries.end( ) )
201 TFilters filters = Self::_DLGetFilters( hnd );
203 // Save the loaded filters info
204 bool save_handler = false;
205 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
207 // Check if the filter is completely new
208 auto act_catIt = this->m_Filters.find( catIt->first );
210 auto clsIt = catIt->second.begin( );
211 clsIt != catIt->second.end( );
215 bool new_filter = true;
216 if( act_catIt != this->m_Filters.end( ) )
218 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
223 // Update filters container
224 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
225 if( creator != NULL )
227 this->m_DynFilters[ catIt->first][ *clsIt ] =
228 TDynFunc( pl_name, creator );
229 this->m_Filters[ catIt->first ].insert( *clsIt );
240 // Keep dynlib handler, if needed
242 this->m_DynLibraries[ pl_name ] = TDynFileInfo( canonical, hnd );
244 Self::_DLClose( hnd );
247 // -------------------------------------------------------------------------
248 void cpPlugins::Interface::
252 auto d = this->m_DynLibraries.begin( );
253 d != this->m_DynLibraries.end( );
256 Self::_DLClose( d->second.second );
257 this->m_DynLibraries.clear( );
258 this->m_DynFilters.clear( );
259 this->m_Filters.clear( );
262 // -------------------------------------------------------------------------
263 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
264 Create( const std::string& category, const std::string& name )
266 typedef cpPlugins::ProcessObject::Pointer _TPointer;
267 _TPointer filter = NULL;
268 auto catIt = this->m_DynFilters.find( category );
269 if( catIt != this->m_DynFilters.end( ) )
271 auto clsIt = catIt->second.find( name );
272 if( clsIt != catIt->second.end( ) )
274 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
281 // -------------------------------------------------------------------------
282 std::string cpPlugins::Interface::
283 GetPluginName( const std::string& category, const std::string& name ) const
285 std::string plugin = "";
286 auto catIt = this->m_DynFilters.find( category );
287 if( catIt != this->m_DynFilters.end( ) )
289 auto clsIt = catIt->second.find( name );
290 if( clsIt != catIt->second.end( ) )
291 plugin = clsIt->second.first;
297 // -------------------------------------------------------------------------
298 std::string cpPlugins::Interface::
299 GetPluginName( const ProcessObject* obj ) const
304 obj->GetClassCategory( ),
312 // -------------------------------------------------------------------------
313 std::set< std::string > cpPlugins::Interface::
316 std::set< std::string > res;
317 auto i = this->m_DynLibraries.begin( );
318 for( ; i != this->m_DynLibraries.end( ); ++i )
319 res.insert( i->first );
323 // -------------------------------------------------------------------------
324 void* cpPlugins::Interface::
325 _DLOpen( const std::string& fname, std::string& error )
328 #ifdef cpPlugins_SYS_WINDOWS
329 hnd = ::LoadLibraryA( fname.c_str( ) );
330 #else // cpPlugins_SYS_WINDOWS
331 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
336 #endif // cpPlugins_SYS_WINDOWS
340 // -------------------------------------------------------------------------
341 const char* cpPlugins::Interface::
342 _DLGetName( void* hnd )
345 typedef const char* ( *f_t )( );
347 #ifdef cpPlugins_SYS_WINDOWS
348 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_Name" ) );
349 #else // cpPlugins_SYS_WINDOWS
350 f = ( f_t )( dlsym( hnd, "cpPlugins_Name" ) );
351 #endif // cpPlugins_SYS_WINDOWS
354 Self::_DLClose( hnd );
355 throw std::runtime_error(
356 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
363 // -------------------------------------------------------------------------
364 cpPlugins::Interface::
365 TFilters cpPlugins::Interface::
366 _DLGetFilters( void* hnd )
369 typedef const char* ( *f_t )( );
371 #ifdef cpPlugins_SYS_WINDOWS
372 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
373 #else // cpPlugins_SYS_WINDOWS
374 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
375 #endif // cpPlugins_SYS_WINDOWS
378 Self::_DLClose( hnd );
379 throw std::runtime_error(
380 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
384 std::string descriptors = f( );
386 // Demangle descriptors
388 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
389 std::istringstream str( descriptors );
392 std::string value, category, name;
396 std::replace( value.begin( ), value.end( ), ':', ' ' );
397 std::istringstream value_str( value );
398 value_str >> category >> name;
399 filters[ category ].insert( name );
405 // -------------------------------------------------------------------------
406 cpPlugins::Interface::
407 TCreator cpPlugins::Interface::
409 void* hnd, const std::string& category, const std::string& name
413 std::string func_name = category + "_" + name;
414 #ifdef cpPlugins_SYS_WINDOWS
415 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
416 #else // cpPlugins_SYS_WINDOWS
417 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
418 #endif // cpPlugins_SYS_WINDOWS
420 throw std::runtime_error(
421 std::string( "cpPlugins::Interface: Class \"" ) +
422 category + std::string( ":" ) + name +
423 std::string( "\" does not have a valid creator function." )
428 // -------------------------------------------------------------------------
429 void cpPlugins::Interface::
430 _DLClose( void* hnd )
432 #ifdef cpPlugins_SYS_WINDOWS
433 ::FreeLibrary( ( HMODULE )hnd );
434 #else // cpPlugins_SYS_WINDOWS
436 #endif // cpPlugins_SYS_WINDOWS