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::
18 // -------------------------------------------------------------------------
19 cpPlugins::Interface::
25 // -------------------------------------------------------------------------
26 const cpPlugins::Interface::
27 TFilters& cpPlugins::Interface::
30 return( this->m_Filters );
33 // -------------------------------------------------------------------------
34 void cpPlugins::Interface::
37 // Load environment configuration
38 this->m_Paths.clear( );
39 char* p = std::getenv( cpPlugins_PATHS );
41 cpPlugins::TokenizeString( this->m_Paths, p, cpPlugins_SEPARATOR );
42 this->m_Paths.push_back( "." );
45 // -------------------------------------------------------------------------
46 void cpPlugins::Interface::
47 GuessAccesiblePlugins( )
49 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
50 try { this->LoadPluginDir( *i ); } catch( ... ) { }
53 // -------------------------------------------------------------------------
54 void cpPlugins::Interface::
55 LoadPlugin( const std::string& name )
57 std::stringstream str;
58 str << cpPlugins_LIB_PREFIX << name << "." << cpPlugins_LIB_EXT;
59 std::string base_name = str.str( );
61 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
63 std::string filename = *i;
64 if( i->back( ) != '/' )
65 filename += std::string( "/" );
66 filename += base_name;
69 this->LoadPluginFile( filename );
78 throw std::runtime_error(
79 std::string( "cpPlugins::Interface: Plugins library \"" ) +
81 std::string( "\" not found." )
85 // -------------------------------------------------------------------------
86 void cpPlugins::Interface::
87 LoadPluginDir( const std::string& dirname )
91 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
93 while( ( ent = readdir( dir ) ) != NULL )
109 throw std::runtime_error(
110 std::string( "cpPlugins::Interface: Could not load directory " ) +
111 std::string( "\"" ) + dirname + std::string( "\"" )
115 // -------------------------------------------------------------------------
116 void cpPlugins::Interface::
117 LoadPluginFile( const std::string& filename )
119 // Canonical filename
120 auto canonical = cpPlugins::CanonicalPath( filename );
121 if( canonical == "" )
122 throw std::runtime_error(
123 std::string( "cpPlugins::Interface: Library \"" ) +
125 std::string( "\" does not exist." )
128 // Try to load the library
129 void* hnd = Self::_DLOpen( canonical );
131 throw std::runtime_error(
132 std::string( "cpPlugins::Interface: Could not load library \"" ) +
138 std::string pl_name = Self::_DLGetName( hnd );
140 // Check if it was already loaded
141 if( this->m_DynLibraries.find( pl_name ) != this->m_DynLibraries.end( ) )
145 TFilters filters = Self::_DLGetFilters( hnd );
147 // Save the loaded filters info
148 bool save_handler = false;
149 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
151 // Check if the filter is completely new
152 auto act_catIt = this->m_Filters.find( catIt->first );
154 auto clsIt = catIt->second.begin( );
155 clsIt != catIt->second.end( );
159 bool new_filter = true;
160 if( act_catIt != this->m_Filters.end( ) )
162 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
167 // Update filters container
168 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
169 if( creator != NULL )
171 this->m_DynFilters[ catIt->first][ *clsIt ] =
172 TDynFunc( pl_name, creator );
173 this->m_Filters[ catIt->first ].insert( *clsIt );
184 // Keep dynlib handler, if needed
186 this->m_DynLibraries[ pl_name ] = TDynFileInfo( canonical, hnd );
188 Self::_DLClose( hnd );
191 // -------------------------------------------------------------------------
192 void cpPlugins::Interface::
196 auto d = this->m_DynLibraries.begin( );
197 d != this->m_DynLibraries.end( );
200 Self::_DLClose( d->second.second );
201 this->m_DynLibraries.clear( );
202 this->m_DynFilters.clear( );
203 this->m_Filters.clear( );
206 // -------------------------------------------------------------------------
207 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
208 Create( const std::string& category, const std::string& name )
210 typedef cpPlugins::ProcessObject::Pointer _TPointer;
211 _TPointer filter = NULL;
212 auto catIt = this->m_DynFilters.find( category );
213 if( catIt != this->m_DynFilters.end( ) )
215 auto clsIt = catIt->second.find( name );
216 if( clsIt != catIt->second.end( ) )
218 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
225 // -------------------------------------------------------------------------
226 std::string cpPlugins::Interface::
227 GetPluginName( const std::string& category, const std::string& name ) const
229 std::string plugin = "";
230 auto catIt = this->m_DynFilters.find( category );
231 if( catIt != this->m_DynFilters.end( ) )
233 auto clsIt = catIt->second.find( name );
234 if( clsIt != catIt->second.end( ) )
235 plugin = clsIt->second.first;
241 // -------------------------------------------------------------------------
242 std::string cpPlugins::Interface::
243 GetPluginName( const ProcessObject* obj ) const
248 obj->GetClassCategory( ),
256 // -------------------------------------------------------------------------
257 std::set< std::string > cpPlugins::Interface::
260 std::set< std::string > res;
261 auto i = this->m_DynLibraries.begin( );
262 for( ; i != this->m_DynLibraries.end( ); ++i )
263 res.insert( i->first );
267 // -------------------------------------------------------------------------
268 void* cpPlugins::Interface::
269 _DLOpen( const std::string& fname )
272 #ifdef cpPlugins_SYS_WINDOWS
273 hnd = ::LoadLibraryA( fname.c_str( ) );
274 #else // cpPlugins_SYS_WINDOWS
275 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
277 #endif // cpPlugins_SYS_WINDOWS
281 // -------------------------------------------------------------------------
282 const char* cpPlugins::Interface::
283 _DLGetName( void* hnd )
286 typedef const char* ( *f_t )( );
288 #ifdef cpPlugins_SYS_WINDOWS
289 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_Name" ) );
290 #else // cpPlugins_SYS_WINDOWS
291 f = ( f_t )( dlsym( hnd, "cpPlugins_Name" ) );
292 #endif // cpPlugins_SYS_WINDOWS
295 Self::_DLClose( hnd );
296 throw std::runtime_error(
297 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
304 // -------------------------------------------------------------------------
305 cpPlugins::Interface::
306 TFilters cpPlugins::Interface::
307 _DLGetFilters( void* hnd )
310 typedef const char* ( *f_t )( );
312 #ifdef cpPlugins_SYS_WINDOWS
313 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
314 #else // cpPlugins_SYS_WINDOWS
315 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
316 #endif // cpPlugins_SYS_WINDOWS
319 Self::_DLClose( hnd );
320 throw std::runtime_error(
321 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
325 std::string descriptors = f( );
327 // Demangle descriptors
329 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
330 std::istringstream str( descriptors );
333 std::string value, category, name;
337 std::replace( value.begin( ), value.end( ), ':', ' ' );
338 std::istringstream value_str( value );
339 value_str >> category >> name;
340 filters[ category ].insert( name );
346 // -------------------------------------------------------------------------
347 cpPlugins::Interface::
348 TCreator cpPlugins::Interface::
350 void* hnd, const std::string& category, const std::string& name
354 std::string func_name = category + "_" + name;
355 #ifdef cpPlugins_SYS_WINDOWS
356 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
357 #else // cpPlugins_SYS_WINDOWS
358 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
359 #endif // cpPlugins_SYS_WINDOWS
361 throw std::runtime_error(
362 std::string( "cpPlugins::Interface: Class \"" ) +
363 category + std::string( ":" ) + name +
364 std::string( "\" does not have a valid creator function." )
369 // -------------------------------------------------------------------------
370 void cpPlugins::Interface::
371 _DLClose( void* hnd )
373 #ifdef cpPlugins_SYS_WINDOWS
374 ::FreeLibrary( ( HMODULE )hnd );
375 #else // cpPlugins_SYS_WINDOWS
377 #endif // cpPlugins_SYS_WINDOWS