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>
11 // -------------------------------------------------------------------------
12 cpPlugins::Interface::
17 // -------------------------------------------------------------------------
18 cpPlugins::Interface::
24 // -------------------------------------------------------------------------
25 const cpPlugins::Interface::
26 TFilters& cpPlugins::Interface::
29 return( this->m_Filters );
32 // -------------------------------------------------------------------------
33 void cpPlugins::Interface::
34 GuessAccesiblePlugins( )
36 // Load environment configuration
37 char* path = std::getenv( "cpPlugins_PATHS" );
40 std::vector< std::string > tokens;
41 cpPlugins::TokenizeString( tokens, path, "#" );
42 for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt )
43 try { this->LoadPluginDir( *tIt ); } catch( ... ) { }
48 auto lpath = cpPlugins::CanonicalPath( "." );
49 try { this->LoadPluginDir( lpath ); } catch( ... ) { }
52 // -------------------------------------------------------------------------
53 bool cpPlugins::Interface::
54 LoadConfiguration( const std::string& filename )
56 std::ifstream in( filename.c_str( ) );
62 while( std::getline( in, line ) )
63 try { this->LoadPluginFile( line ); } catch( ... ) { }
67 // -------------------------------------------------------------------------
68 bool cpPlugins::Interface::
69 SaveConfiguration( const std::string& filename ) const
71 std::ofstream out( filename.c_str( ) );
74 auto dIt = this->m_DynLibraries.begin( );
75 for( ; dIt != this->m_DynLibraries.end( ); ++dIt )
76 out << dIt->first << std::endl;
81 // -------------------------------------------------------------------------
82 void cpPlugins::Interface::
83 LoadPluginFile( const std::string& filename )
85 // Open library with its canonical path name
86 auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
87 if( canonical_fn == "" )
88 throw std::runtime_error(
89 std::string( "cpPlugins::Interface: Library \"" ) +
91 std::string( "\" does not exist." )
94 // Check if it was already loaded
96 this->m_DynLibraries.find( canonical_fn ) != this->m_DynLibraries.end( )
100 // Ok, try to load the library
101 void* hnd = Self::_DLOpen( canonical_fn );
103 throw std::runtime_error(
104 std::string( "cpPlugins::Interface: Could not load library \"" ) +
110 TFilters filters = Self::_DLGetFilters( hnd );
112 // Save the loaded filters info
113 bool save_handler = false;
114 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
116 // Check if the filter is completely new
117 auto act_catIt = this->m_Filters.find( catIt->first );
119 auto clsIt = catIt->second.begin( );
120 clsIt != catIt->second.end( );
124 bool new_filter = true;
125 if( act_catIt != this->m_Filters.end( ) )
127 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
132 // Update filters container
133 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
134 if( creator != NULL )
136 this->m_DynFilters[ catIt->first][ *clsIt ] =
137 TDynFunc( canonical_fn, creator );
138 this->m_Filters[ catIt->first ].insert( *clsIt );
149 // Keep dynlib handler, if needed
151 this->m_DynLibraries[ canonical_fn ] = hnd;
153 Self::_DLClose( hnd );
156 // -------------------------------------------------------------------------
157 unsigned int cpPlugins::Interface::
158 LoadPluginDir( const std::string& dirname )
162 unsigned int count = 0;
163 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
165 while( ( ent = readdir( dir ) ) != NULL )
169 this->LoadPluginFile(
182 throw std::runtime_error(
183 std::string( "cpPlugins::Interface: Could not load directory " ) +
184 std::string( "\"" ) + dirname + std::string( "\"" )
189 // -------------------------------------------------------------------------
190 void cpPlugins::Interface::
194 auto d = this->m_DynLibraries.begin( );
195 d != this->m_DynLibraries.end( );
198 Self::_DLClose( d->second );
199 this->m_DynLibraries.clear( );
200 this->m_DynFilters.clear( );
201 this->m_Filters.clear( );
204 // -------------------------------------------------------------------------
205 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
206 Create( const std::string& category, const std::string& name )
208 typedef cpPlugins::ProcessObject::Pointer _TPointer;
209 _TPointer filter = NULL;
210 auto catIt = this->m_DynFilters.find( category );
211 if( catIt != this->m_DynFilters.end( ) )
213 auto clsIt = catIt->second.find( name );
214 if( clsIt != catIt->second.end( ) )
216 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
223 // -------------------------------------------------------------------------
224 void* cpPlugins::Interface::
225 _DLOpen( const std::string& fname )
228 #ifdef cpPlugins_SYS_WINDOWS
229 hnd = ::LoadLibraryA( fname.c_str( ) );
230 #else // cpPlugins_SYS_WINDOWS
231 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
233 #endif // cpPlugins_SYS_WINDOWS
237 // -------------------------------------------------------------------------
238 cpPlugins::Interface::
239 TFilters cpPlugins::Interface::
240 _DLGetFilters( void* hnd )
243 typedef const char* ( *f_t )( );
245 #ifdef cpPlugins_SYS_WINDOWS
246 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
247 #else // cpPlugins_SYS_WINDOWS
248 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
249 #endif // cpPlugins_SYS_WINDOWS
252 Self::_DLClose( hnd );
253 throw std::runtime_error(
254 "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
258 std::string descriptors = f( );
260 // Demangle descriptors
262 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
263 std::istringstream str( descriptors );
266 std::string value, category, name;
270 std::replace( value.begin( ), value.end( ), ':', ' ' );
271 std::istringstream value_str( value );
272 value_str >> category >> name;
273 filters[ category ].insert( name );
279 // -------------------------------------------------------------------------
280 cpPlugins::Interface::
281 TCreator cpPlugins::Interface::
283 void* hnd, const std::string& category, const std::string& name
287 std::string func_name = category + "_" + name;
288 #ifdef cpPlugins_SYS_WINDOWS
289 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
290 #else // cpPlugins_SYS_WINDOWS
291 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
292 #endif // cpPlugins_SYS_WINDOWS
294 throw std::runtime_error(
295 std::string( "cpPlugins::Interface: Class \"" ) +
296 category + std::string( ":" ) + name +
297 std::string( "\" does not have a valid creator function." )
302 // -------------------------------------------------------------------------
303 void cpPlugins::Interface::
304 _DLClose( void* hnd )
306 #ifdef cpPlugins_SYS_WINDOWS
307 ::FreeLibrary( ( HMODULE )hnd );
308 #else // cpPlugins_SYS_WINDOWS
310 #endif // cpPlugins_SYS_WINDOWS