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 if( canonical_fn == "" )
77 throw std::runtime_error(
78 std::string( "cpPlugins::Interface: Library \"" ) +
80 std::string( "\" does not exist." )
82 void* hnd = Self::_DLOpen( canonical_fn );
84 throw std::runtime_error(
85 std::string( "cpPlugins::Interface: Could not load library \"" ) +
91 TFilters filters = Self::_DLGetFilters( hnd );
93 // Save the loaded filters info
94 bool save_handler = false;
95 for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
97 // Check if the filter is completely new
98 auto act_catIt = this->m_Filters.find( catIt->first );
100 auto clsIt = catIt->second.begin( );
101 clsIt != catIt->second.end( );
105 bool new_filter = true;
106 if( act_catIt != this->m_Filters.end( ) )
108 ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
113 // Update filters container
114 auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
115 if( creator != NULL )
117 this->m_DynFilters[ catIt->first][ *clsIt ] =
118 TDynFunc( canonical_fn, creator );
119 this->m_Filters[ catIt->first ].insert( *clsIt );
130 // Keep dynlib handler, if needed
132 this->m_DynLibraries[ canonical_fn ] = hnd;
134 Self::_DLClose( hnd );
137 // -------------------------------------------------------------------------
138 void cpPlugins::Interface::
142 auto d = this->m_DynLibraries.begin( );
143 d != this->m_DynLibraries.end( );
146 Self::_DLClose( d->second );
147 this->m_DynLibraries.clear( );
148 this->m_DynFilters.clear( );
149 this->m_Filters.clear( );
152 // -------------------------------------------------------------------------
153 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
154 Create( const std::string& category, const std::string& name )
156 typedef cpPlugins::ProcessObject::Pointer _TPointer;
157 _TPointer filter = NULL;
158 auto catIt = this->m_DynFilters.find( category );
159 if( catIt != this->m_DynFilters.end( ) )
161 auto clsIt = catIt->second.find( name );
162 if( clsIt != catIt->second.end( ) )
164 ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
171 // -------------------------------------------------------------------------
172 void* cpPlugins::Interface::
173 _DLOpen( const std::string& fname )
176 #ifdef cpPlugins_SYS_WINDOWS
177 hnd = ::LoadLibraryA( fname.c_str( ) );
178 #else // cpPlugins_SYS_WINDOWS
179 hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
181 #endif // cpPlugins_SYS_WINDOWS
185 // -------------------------------------------------------------------------
186 cpPlugins::Interface::
187 TFilters cpPlugins::Interface::
188 _DLGetFilters( void* hnd )
191 typedef const char* ( *f_t )( );
193 #ifdef cpPlugins_SYS_WINDOWS
194 f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
195 #else // cpPlugins_SYS_WINDOWS
196 f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
197 #endif // cpPlugins_SYS_WINDOWS
200 Self::_DLClose( hnd );
201 throw std::runtime_error(
202 "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
206 std::string descriptors = f( );
208 // Demangle descriptors
210 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
211 std::istringstream str( descriptors );
214 std::string value, category, name;
218 std::replace( value.begin( ), value.end( ), ':', ' ' );
219 std::istringstream value_str( value );
220 value_str >> category >> name;
221 filters[ category ].insert( name );
227 // -------------------------------------------------------------------------
228 cpPlugins::Interface::
229 TCreator cpPlugins::Interface::
231 void* hnd, const std::string& category, const std::string& name
235 std::string func_name = category + "_" + name;
236 #ifdef cpPlugins_SYS_WINDOWS
237 c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
238 #else // cpPlugins_SYS_WINDOWS
239 c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
240 #endif // cpPlugins_SYS_WINDOWS
242 throw std::runtime_error(
243 std::string( "cpPlugins::Interface: Class \"" ) +
244 category + std::string( ":" ) + name +
245 std::string( "\" does not have a valid creator function." )
250 // -------------------------------------------------------------------------
251 void cpPlugins::Interface::
252 _DLClose( void* hnd )
254 #ifdef cpPlugins_SYS_WINDOWS
255 ::FreeLibrary( ( HMODULE )hnd );
256 #else // cpPlugins_SYS_WINDOWS
258 #endif // cpPlugins_SYS_WINDOWS