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>
10 // -------------------------------------------------------------------------
11 cpPlugins::Interface::
16 // -------------------------------------------------------------------------
17 cpPlugins::Interface::
23 // -------------------------------------------------------------------------
24 const cpPlugins::Interface::
25 TFilters& cpPlugins::Interface::
28 return( this->m_Filters );
31 // -------------------------------------------------------------------------
32 bool cpPlugins::Interface::
33 LoadConfiguration( const std::string& filename )
35 std::ifstream in( filename.c_str( ) );
41 while( std::getline( in, line ) )
45 this->LoadPluginFile( line );
57 // -------------------------------------------------------------------------
58 bool cpPlugins::Interface::
59 SaveConfiguration( const std::string& filename ) const
61 std::ofstream out( filename.c_str( ) );
64 auto dIt = this->m_DynLibraries.begin( );
65 for( ; dIt != this->m_DynLibraries.end( ); ++dIt )
66 out << dIt->first << std::endl;
71 // -------------------------------------------------------------------------
72 void cpPlugins::Interface::
73 LoadPluginFile( const std::string& filename )
75 // Open library with its canonical path name
76 auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
77 if( canonical_fn == "" )
78 throw std::runtime_error(
79 std::string( "cpPlugins::Interface: Library \"" ) +
81 std::string( "\" does not exist." )
84 // Check if it was already loaded
86 this->m_DynLibraries.find( canonical_fn ) != this->m_DynLibraries.end( )
90 // Ok, try to load the library
91 void* hnd = Self::_DLOpen( canonical_fn );
93 throw std::runtime_error(
94 std::string( "cpPlugins::Interface: Could not load library \"" ) +
100 TFilters filters = Self::_DLGetFilters( hnd );
102 // Save the loaded filters info
103 bool save_handler = false;
104 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
106 // Check if the filter is completely new
107 auto act_catIt = this->m_Filters.find( catIt->first );
109 auto clsIt = catIt->second.begin( );
110 clsIt != catIt->second.end( );
114 bool new_filter = true;
115 if( act_catIt != this->m_Filters.end( ) )
117 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
122 // Update filters container
123 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
124 if( creator != NULL )
126 this->m_DynFilters[ catIt->first][ *clsIt ] =
127 TDynFunc( canonical_fn, creator );
128 this->m_Filters[ catIt->first ].insert( *clsIt );
139 // Keep dynlib handler, if needed
141 this->m_DynLibraries[ canonical_fn ] = hnd;
143 Self::_DLClose( hnd );
146 // -------------------------------------------------------------------------
147 unsigned int cpPlugins::Interface::
148 LoadPluginDir( const std::string& dirname )
152 unsigned int count = 0;
153 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
155 while( ( ent = readdir( dir ) ) != NULL )
159 this->LoadPluginFile(
174 throw std::runtime_error(
175 std::string( "cpPlugins::Interface: Could not load directory " ) +
176 std::string( "\"" ) + dirname + std::string( "\"" )
181 // -------------------------------------------------------------------------
182 void cpPlugins::Interface::
186 auto d = this->m_DynLibraries.begin( );
187 d != this->m_DynLibraries.end( );
190 Self::_DLClose( d->second );
191 this->m_DynLibraries.clear( );
192 this->m_DynFilters.clear( );
193 this->m_Filters.clear( );
196 // -------------------------------------------------------------------------
197 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
198 Create( const std::string& category, const std::string& name )
200 typedef cpPlugins::ProcessObject::Pointer _TPointer;
201 _TPointer filter = NULL;
202 auto catIt = this->m_DynFilters.find( category );
203 if( catIt != this->m_DynFilters.end( ) )
205 auto clsIt = catIt->second.find( name );
206 if( clsIt != catIt->second.end( ) )
208 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
215 // -------------------------------------------------------------------------
216 void* cpPlugins::Interface::
217 _DLOpen( const std::string& fname )
220 #ifdef cpPlugins_SYS_WINDOWS
221 hnd = ::LoadLibraryA( fname.c_str( ) );
222 #else // cpPlugins_SYS_WINDOWS
223 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
225 #endif // cpPlugins_SYS_WINDOWS
229 // -------------------------------------------------------------------------
230 cpPlugins::Interface::
231 TFilters cpPlugins::Interface::
232 _DLGetFilters( void* hnd )
235 typedef const char* ( *f_t )( );
237 #ifdef cpPlugins_SYS_WINDOWS
238 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
239 #else // cpPlugins_SYS_WINDOWS
240 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
241 #endif // cpPlugins_SYS_WINDOWS
244 Self::_DLClose( hnd );
245 throw std::runtime_error(
246 "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
250 std::string descriptors = f( );
252 // Demangle descriptors
254 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
255 std::istringstream str( descriptors );
258 std::string value, category, name;
262 std::replace( value.begin( ), value.end( ), ':', ' ' );
263 std::istringstream value_str( value );
264 value_str >> category >> name;
265 filters[ category ].insert( name );
271 // -------------------------------------------------------------------------
272 cpPlugins::Interface::
273 TCreator cpPlugins::Interface::
275 void* hnd, const std::string& category, const std::string& name
279 std::string func_name = category + "_" + name;
280 #ifdef cpPlugins_SYS_WINDOWS
281 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
282 #else // cpPlugins_SYS_WINDOWS
283 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
284 #endif // cpPlugins_SYS_WINDOWS
286 throw std::runtime_error(
287 std::string( "cpPlugins::Interface: Class \"" ) +
288 category + std::string( ":" ) + name +
289 std::string( "\" does not have a valid creator function." )
294 // -------------------------------------------------------------------------
295 void cpPlugins::Interface::
296 _DLClose( void* hnd )
298 #ifdef cpPlugins_SYS_WINDOWS
299 ::FreeLibrary( ( HMODULE )hnd );
300 #else // cpPlugins_SYS_WINDOWS
302 #endif // cpPlugins_SYS_WINDOWS