]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Interface.cxx
...
[cpPlugins.git] / lib / cpPlugins / Interface.cxx
1 #include <cpPlugins/Interface.h>
2
3 #ifdef cpPlugins_SYS_WINDOWS
4 #  include <Windows.h>
5 #else // cpPlugins_SYS_WINDOWS
6 #  include <dlfcn.h>
7 #endif // cpPlugins_SYS_WINDOWS
8 #include <cpPlugins_dirent.h>
9
10 // -------------------------------------------------------------------------
11 cpPlugins::Interface::
12 Interface( )
13 {
14 }
15
16 // -------------------------------------------------------------------------
17 cpPlugins::Interface::
18 ~Interface( )
19 {
20   this->UnloadAll( );
21 }
22
23 // -------------------------------------------------------------------------
24 const cpPlugins::Interface::
25 TFilters& cpPlugins::Interface::
26 GetFilters( )
27 {
28   return( this->m_Filters );
29 }
30
31 // -------------------------------------------------------------------------
32 bool cpPlugins::Interface::
33 LoadConfiguration( const std::string& filename )
34 {
35   std::ifstream in( filename.c_str( ) );
36   if( !in )
37     return( false );
38
39   this->UnloadAll( );
40   std::string line;
41   while( std::getline( in, line ) )
42   {
43     try
44     {
45       this->LoadPluginFile( line );
46     }
47     catch( ... )
48     {
49       // Do nothing
50
51     } // yrt
52
53   } // elihw
54   return( true );
55 }
56
57 // -------------------------------------------------------------------------
58 bool cpPlugins::Interface::
59 SaveConfiguration( const std::string& filename ) const
60 {
61   std::ofstream out( filename.c_str( ) );
62   if( !out )
63     return( false );
64   auto dIt = this->m_DynLibraries.begin( );
65   for( ; dIt != this->m_DynLibraries.end( ); ++dIt )
66     out << dIt->first << std::endl;
67   out.close( );
68   return( true );
69 }
70
71 // -------------------------------------------------------------------------
72 void cpPlugins::Interface::
73 LoadPluginFile( const std::string& filename )
74 {
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 \"" ) +
80       filename +
81       std::string( "\" does not exist." )
82       );
83   void* hnd = Self::_DLOpen( canonical_fn );
84   if( hnd == NULL )
85     throw std::runtime_error(
86       std::string( "cpPlugins::Interface: Could not load library \"" ) +
87       filename +
88       std::string( "\"" )
89       );
90
91   // Load filters
92   TFilters filters = Self::_DLGetFilters( hnd );
93
94   // Save the loaded filters info
95   bool save_handler = false;
96   for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
97   {
98     // Check if the filter is completely new
99     auto act_catIt = this->m_Filters.find( catIt->first );
100     for(
101       auto clsIt = catIt->second.begin( );
102       clsIt != catIt->second.end( );
103       ++clsIt
104       )
105     {
106       bool new_filter = true;
107       if( act_catIt != this->m_Filters.end( ) )
108         new_filter =
109           ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
110
111       // Ok, it is new
112       if( new_filter )
113       {
114         // Update filters container
115         auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
116         if( creator != NULL )
117         {
118           this->m_DynFilters[ catIt->first][ *clsIt ] =
119             TDynFunc( canonical_fn, creator );
120           this->m_Filters[ catIt->first ].insert( *clsIt );
121           save_handler = true;
122
123         } // fi
124
125       } // fi
126
127     } // rof
128
129   } // rof
130
131   // Keep dynlib handler, if needed
132   if( save_handler )
133     this->m_DynLibraries[ canonical_fn ] = hnd;
134   else
135     Self::_DLClose( hnd );
136 }
137
138 // -------------------------------------------------------------------------
139 void cpPlugins::Interface::
140 LoadPluginDir( const std::string& dirname )
141 {
142 #error ACA VOY
143   DIR *dir;
144   struct dirent *ent;
145   if( (dir = opendir ( dirname.c_str( ) ) ) != NULL)
146   {
147     while ((ent = readdir (dir)) != NULL) {
148       printf ("%s\n", ent->d_name);
149     }
150     closedir (dir);
151   } else {
152     std::cerr << "error" << std::endl;
153   }
154 }
155
156 // -------------------------------------------------------------------------
157 void cpPlugins::Interface::
158 UnloadAll( )
159 {
160   for(
161     auto d = this->m_DynLibraries.begin( );
162     d != this->m_DynLibraries.end( );
163     ++d
164     )
165     Self::_DLClose( d->second );
166   this->m_DynLibraries.clear( );
167   this->m_DynFilters.clear( );
168   this->m_Filters.clear( );
169 }
170
171 // -------------------------------------------------------------------------
172 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
173 Create( const std::string& category, const std::string& name )
174 {
175   typedef cpPlugins::ProcessObject::Pointer _TPointer;
176   _TPointer filter = NULL;
177   auto catIt = this->m_DynFilters.find( category );
178   if( catIt != this->m_DynFilters.end( ) )
179   {
180     auto clsIt = catIt->second.find( name );
181     if( clsIt != catIt->second.end( ) )
182       filter =
183         ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
184         GetPointer( );
185
186   } // fi
187   return( filter );
188 }
189
190 // -------------------------------------------------------------------------
191 void* cpPlugins::Interface::
192 _DLOpen( const std::string& fname )
193 {
194   void* hnd = NULL;
195 #ifdef cpPlugins_SYS_WINDOWS
196   hnd = ::LoadLibraryA( fname.c_str( ) );
197 #else // cpPlugins_SYS_WINDOWS
198   hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
199   dlerror( );
200 #endif // cpPlugins_SYS_WINDOWS
201   return( hnd );
202 }
203
204 // -------------------------------------------------------------------------
205 cpPlugins::Interface::
206 TFilters cpPlugins::Interface::
207 _DLGetFilters( void* hnd )
208 {
209   // Get descriptors
210   typedef const char* ( *f_t )( );
211   f_t f = NULL;
212 #ifdef cpPlugins_SYS_WINDOWS
213   f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
214 #else // cpPlugins_SYS_WINDOWS
215   f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
216 #endif // cpPlugins_SYS_WINDOWS
217   if( f == NULL )
218   {
219     Self::_DLClose( hnd );
220     throw std::runtime_error(
221       "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
222       );
223
224   } // fi
225   std::string descriptors = f( );
226
227   // Demangle descriptors
228   TFilters filters;
229   std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
230   std::istringstream str( descriptors );
231   while( str )
232   {
233     std::string value, category, name;
234     str >> value;
235     if( value == "" )
236       continue;
237     std::replace( value.begin( ), value.end( ), ':', ' ' );
238     std::istringstream value_str( value );
239     value_str >> category >> name;
240     filters[ category ].insert( name );
241
242   } // elihw
243   return( filters );
244 }
245
246 // -------------------------------------------------------------------------
247 cpPlugins::Interface::
248 TCreator cpPlugins::Interface::
249 _DLGetCreator(
250   void* hnd, const std::string& category, const std::string& name
251   )
252 {
253   TCreator c = NULL;
254   std::string func_name = category + "_" + name;
255 #ifdef cpPlugins_SYS_WINDOWS
256   c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
257 #else // cpPlugins_SYS_WINDOWS
258   c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
259 #endif // cpPlugins_SYS_WINDOWS
260   if( c == NULL )
261     throw std::runtime_error(
262       std::string( "cpPlugins::Interface: Class \"" ) +
263       category + std::string( ":" ) + name +
264       std::string( "\" does not have a valid creator function." )
265       );
266   return( c );
267 }
268
269 // -------------------------------------------------------------------------
270 void cpPlugins::Interface::
271 _DLClose( void* hnd )
272 {
273 #ifdef cpPlugins_SYS_WINDOWS
274   ::FreeLibrary( ( HMODULE )hnd );
275 #else // cpPlugins_SYS_WINDOWS
276   dlclose( hnd );
277 #endif // cpPlugins_SYS_WINDOWS
278 }
279
280 // eof - $RCSfile$