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
85 if( this->m_DynLibraries.find( canonical_fn ) != this->m_DynLibraries.end( ) )
88 // Ok, try to load the library
89 void* hnd = Self::_DLOpen( canonical_fn );
91 throw std::runtime_error(
92 std::string( "cpPlugins::Interface: Could not load library \"" ) +
98 TFilters filters = Self::_DLGetFilters( hnd );
100 // Save the loaded filters info
101 bool save_handler = false;
102 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
104 // Check if the filter is completely new
105 auto act_catIt = this->m_Filters.find( catIt->first );
107 auto clsIt = catIt->second.begin( );
108 clsIt != catIt->second.end( );
112 bool new_filter = true;
113 if( act_catIt != this->m_Filters.end( ) )
115 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
120 // Update filters container
121 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
122 if( creator != NULL )
124 this->m_DynFilters[ catIt->first][ *clsIt ] =
125 TDynFunc( canonical_fn, creator );
126 this->m_Filters[ catIt->first ].insert( *clsIt );
137 // Keep dynlib handler, if needed
139 this->m_DynLibraries[ canonical_fn ] = hnd;
141 Self::_DLClose( hnd );
144 // -------------------------------------------------------------------------
145 unsigned int cpPlugins::Interface::
146 LoadPluginDir( const std::string& dirname )
150 unsigned int count = 0;
151 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
153 while( ( ent = readdir( dir ) ) != NULL )
157 this->LoadPluginFile( ent->d_name );
168 throw std::runtime_error(
169 std::string( "cpPlugins::Interface: Could not load directory " ) +
170 std::string( "\"" ) + dirname + std::string( "\"" )
175 // -------------------------------------------------------------------------
176 void cpPlugins::Interface::
180 auto d = this->m_DynLibraries.begin( );
181 d != this->m_DynLibraries.end( );
184 Self::_DLClose( d->second );
185 this->m_DynLibraries.clear( );
186 this->m_DynFilters.clear( );
187 this->m_Filters.clear( );
190 // -------------------------------------------------------------------------
191 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
192 Create( const std::string& category, const std::string& name )
194 typedef cpPlugins::ProcessObject::Pointer _TPointer;
195 _TPointer filter = NULL;
196 auto catIt = this->m_DynFilters.find( category );
197 if( catIt != this->m_DynFilters.end( ) )
199 auto clsIt = catIt->second.find( name );
200 if( clsIt != catIt->second.end( ) )
202 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
209 // -------------------------------------------------------------------------
210 void* cpPlugins::Interface::
211 _DLOpen( const std::string& fname )
214 #ifdef cpPlugins_SYS_WINDOWS
215 hnd = ::LoadLibraryA( fname.c_str( ) );
216 #else // cpPlugins_SYS_WINDOWS
217 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
219 #endif // cpPlugins_SYS_WINDOWS
223 // -------------------------------------------------------------------------
224 cpPlugins::Interface::
225 TFilters cpPlugins::Interface::
226 _DLGetFilters( void* hnd )
229 typedef const char* ( *f_t )( );
231 #ifdef cpPlugins_SYS_WINDOWS
232 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
233 #else // cpPlugins_SYS_WINDOWS
234 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
235 #endif // cpPlugins_SYS_WINDOWS
238 Self::_DLClose( hnd );
239 throw std::runtime_error(
240 "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
244 std::string descriptors = f( );
246 // Demangle descriptors
248 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
249 std::istringstream str( descriptors );
252 std::string value, category, name;
256 std::replace( value.begin( ), value.end( ), ':', ' ' );
257 std::istringstream value_str( value );
258 value_str >> category >> name;
259 filters[ category ].insert( name );
265 // -------------------------------------------------------------------------
266 cpPlugins::Interface::
267 TCreator cpPlugins::Interface::
269 void* hnd, const std::string& category, const std::string& name
273 std::string func_name = category + "_" + name;
274 #ifdef cpPlugins_SYS_WINDOWS
275 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
276 #else // cpPlugins_SYS_WINDOWS
277 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
278 #endif // cpPlugins_SYS_WINDOWS
280 throw std::runtime_error(
281 std::string( "cpPlugins::Interface: Class \"" ) +
282 category + std::string( ":" ) + name +
283 std::string( "\" does not have a valid creator function." )
288 // -------------------------------------------------------------------------
289 void cpPlugins::Interface::
290 _DLClose( void* hnd )
292 #ifdef cpPlugins_SYS_WINDOWS
293 ::FreeLibrary( ( HMODULE )hnd );
294 #else // cpPlugins_SYS_WINDOWS
296 #endif // cpPlugins_SYS_WINDOWS