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::PathHelper::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::vector< std::string > cpPlugins::Interface::
245 std::vector< std::string > res;
246 auto i = this->m_DynLibraries.begin( );
247 for( ; i != this->m_DynLibraries.end( ); ++i )
248 res.push_back( i->first );
252 // -------------------------------------------------------------------------
253 void* cpPlugins::Interface::
254 _DLOpen( const std::string& fname )
257 #ifdef cpPlugins_SYS_WINDOWS
258 hnd = ::LoadLibraryA( fname.c_str( ) );
259 #else // cpPlugins_SYS_WINDOWS
260 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
262 #endif // cpPlugins_SYS_WINDOWS
266 // -------------------------------------------------------------------------
267 const char* cpPlugins::Interface::
268 _DLGetName( void* hnd )
271 typedef const char* ( *f_t )( );
273 #ifdef cpPlugins_SYS_WINDOWS
274 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_Name" ) );
275 #else // cpPlugins_SYS_WINDOWS
276 f = ( f_t )( dlsym( hnd, "cpPlugins_Name" ) );
277 #endif // cpPlugins_SYS_WINDOWS
280 Self::_DLClose( hnd );
281 throw std::runtime_error(
282 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
289 // -------------------------------------------------------------------------
290 cpPlugins::Interface::
291 TFilters cpPlugins::Interface::
292 _DLGetFilters( void* hnd )
295 typedef const char* ( *f_t )( );
297 #ifdef cpPlugins_SYS_WINDOWS
298 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
299 #else // cpPlugins_SYS_WINDOWS
300 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
301 #endif // cpPlugins_SYS_WINDOWS
304 Self::_DLClose( hnd );
305 throw std::runtime_error(
306 "cpPlugins::Interface: Library not recognized as a cpPlugins library."
310 std::string descriptors = f( );
312 // Demangle descriptors
314 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
315 std::istringstream str( descriptors );
318 std::string value, category, name;
322 std::replace( value.begin( ), value.end( ), ':', ' ' );
323 std::istringstream value_str( value );
324 value_str >> category >> name;
325 filters[ category ].insert( name );
331 // -------------------------------------------------------------------------
332 cpPlugins::Interface::
333 TCreator cpPlugins::Interface::
335 void* hnd, const std::string& category, const std::string& name
339 std::string func_name = category + "_" + name;
340 #ifdef cpPlugins_SYS_WINDOWS
341 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
342 #else // cpPlugins_SYS_WINDOWS
343 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
344 #endif // cpPlugins_SYS_WINDOWS
346 throw std::runtime_error(
347 std::string( "cpPlugins::Interface: Class \"" ) +
348 category + std::string( ":" ) + name +
349 std::string( "\" does not have a valid creator function." )
354 // -------------------------------------------------------------------------
355 void cpPlugins::Interface::
356 _DLClose( void* hnd )
358 #ifdef cpPlugins_SYS_WINDOWS
359 ::FreeLibrary( ( HMODULE )hnd );
360 #else // cpPlugins_SYS_WINDOWS
362 #endif // cpPlugins_SYS_WINDOWS