1 #include <cpPlugins/Interface.h>
3 #ifdef cpPlugins_SYS_WINDOWS
5 #else // cpPlugins_SYS_WINDOWS
7 #endif // cpPlugins_SYS_WINDOWS
9 // -------------------------------------------------------------------------
10 cpPlugins::Interface::
15 // -------------------------------------------------------------------------
16 cpPlugins::Interface::
22 // -------------------------------------------------------------------------
23 const cpPlugins::Interface::
24 TFilters& cpPlugins::Interface::
27 return( this->m_Filters );
30 // -------------------------------------------------------------------------
31 bool cpPlugins::Interface::
32 LoadConfiguration( const std::string& filename )
34 std::ifstream in( filename.c_str( ) );
40 while( std::getline( in, line ) )
44 this->LoadPluginFile( line );
56 // -------------------------------------------------------------------------
57 bool cpPlugins::Interface::
58 SaveConfiguration( const std::string& filename ) const
60 std::ofstream out( filename.c_str( ) );
63 auto dIt = this->m_DynLibraries.begin( );
64 for( ; dIt != this->m_DynLibraries.end( ); ++dIt )
65 out << dIt->first << std::endl;
70 // -------------------------------------------------------------------------
71 void cpPlugins::Interface::
72 LoadPluginFile( const std::string& filename )
74 // Open library with its canonical path name
75 auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
76 void* hnd = Self::_DLOpen( canonical_fn );
78 throw std::runtime_error(
79 std::string( "cpPlugins::Interface: Could not load library \"" ) +
85 TFilters filters = Self::_DLGetFilters( hnd );
87 // Save the loaded filters info
88 bool save_handler = false;
89 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
91 // Check if the filter is completely new
92 auto act_catIt = this->m_Filters.find( catIt->first );
94 auto clsIt = catIt->second.begin( );
95 clsIt != catIt->second.end( );
99 bool new_filter = true;
100 if( act_catIt != this->m_Filters.end( ) )
102 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
107 // Update filters container
108 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
109 if( creator != NULL )
111 this->m_DynFilters[ catIt->first][ *clsIt ] =
112 TDynFunc( canonical_fn, creator );
113 this->m_Filters[ catIt->first ].insert( *clsIt );
124 // Keep dynlib handler, if needed
126 this->m_DynLibraries[ canonical_fn ] = hnd;
128 Self::_DLClose( hnd );
131 // -------------------------------------------------------------------------
132 void cpPlugins::Interface::
136 auto d = this->m_DynLibraries.begin( );
137 d != this->m_DynLibraries.end( );
140 Self::_DLClose( d->second );
141 this->m_DynLibraries.clear( );
142 this->m_DynFilters.clear( );
143 this->m_Filters.clear( );
146 // -------------------------------------------------------------------------
147 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
148 Create( const std::string& category, const std::string& name )
150 typedef cpPlugins::ProcessObject::Pointer _TPointer;
151 _TPointer filter = NULL;
152 auto catIt = this->m_DynFilters.find( category );
153 if( catIt != this->m_DynFilters.end( ) )
155 auto clsIt = catIt->second.find( name );
156 if( clsIt != catIt->second.end( ) )
158 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
165 // -------------------------------------------------------------------------
166 void* cpPlugins::Interface::
167 _DLOpen( const std::string& fname )
170 #ifdef cpPlugins_SYS_WINDOWS
171 hnd = ::LoadLibraryA( fname.c_str( ) );
172 #else // cpPlugins_SYS_WINDOWS
173 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
175 #endif // cpPlugins_SYS_WINDOWS
179 // -------------------------------------------------------------------------
180 cpPlugins::Interface::
181 TFilters cpPlugins::Interface::
182 _DLGetFilters( void* hnd )
185 typedef const char* ( *f_t )( );
187 #ifdef cpPlugins_SYS_WINDOWS
188 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
189 #else // cpPlugins_SYS_WINDOWS
190 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
191 #endif // cpPlugins_SYS_WINDOWS
194 Self::_DLClose( hnd );
195 throw std::runtime_error(
196 "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
200 std::string descriptors = f( );
202 // Demangle descriptors
204 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
205 std::istringstream str( descriptors );
208 std::string value, category, name;
212 std::replace( value.begin( ), value.end( ), ':', ' ' );
213 std::istringstream value_str( value );
214 value_str >> category >> name;
215 filters[ category ].insert( name );
221 // -------------------------------------------------------------------------
222 cpPlugins::Interface::
223 TCreator cpPlugins::Interface::
225 void* hnd, const std::string& category, const std::string& name
229 std::string func_name = category + "_" + name;
230 #ifdef cpPlugins_SYS_WINDOWS
231 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
232 #else // cpPlugins_SYS_WINDOWS
233 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
234 #endif // cpPlugins_SYS_WINDOWS
236 throw std::runtime_error(
237 std::string( "cpPlugins::Interface: Class \"" ) +
238 category + std::string( ":" ) + name +
239 std::string( "\" does not have a valid creator function." )
244 // -------------------------------------------------------------------------
245 void cpPlugins::Interface::
246 _DLClose( void* hnd )
248 #ifdef cpPlugins_SYS_WINDOWS
249 ::FreeLibrary( ( HMODULE )hnd );
250 #else // cpPlugins_SYS_WINDOWS
252 #endif // cpPlugins_SYS_WINDOWS