]> 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
9 // -------------------------------------------------------------------------
10 cpPlugins::Interface::
11 Interface( )
12 {
13 }
14
15 // -------------------------------------------------------------------------
16 cpPlugins::Interface::
17 ~Interface( )
18 {
19   this->UnloadAll( );
20 }
21
22 // -------------------------------------------------------------------------
23 const cpPlugins::Interface::
24 TFilters& cpPlugins::Interface::
25 GetFilters( )
26 {
27   return( this->m_Filters );
28 }
29
30 // -------------------------------------------------------------------------
31 bool cpPlugins::Interface::
32 LoadConfiguration( const std::string& filename )
33 {
34   std::ifstream in( filename.c_str( ) );
35   if( !in )
36     return( false );
37
38   this->UnloadAll( );
39   std::string line;
40   while( std::getline( in, line ) )
41   {
42     try
43     {
44       this->LoadPluginFile( line );
45     }
46     catch( ... )
47     {
48       // Do nothing
49
50     } // yrt
51
52   } // elihw
53   return( true );
54 }
55
56 // -------------------------------------------------------------------------
57 bool cpPlugins::Interface::
58 SaveConfiguration( const std::string& filename ) const
59 {
60   std::ofstream out( filename.c_str( ) );
61   if( !out )
62     return( false );
63   auto dIt = this->m_DynLibraries.begin( );
64   for( ; dIt != this->m_DynLibraries.end( ); ++dIt )
65     out << dIt->first << std::endl;
66   out.close( );
67 }
68
69 // -------------------------------------------------------------------------
70 void cpPlugins::Interface::
71 LoadPluginFile( const std::string& filename )
72 {
73   // Open library with its canonical path name
74   auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
75   void* hnd = Self::_DLOpen( canonical_fn );
76   if( hnd == NULL )
77     throw std::runtime_error(
78       std::string( "cpPlugins::Interface: Could not load library \"" ) +
79       canonical_fn +
80       std::string( "\"" )
81       );
82
83   // Load filters
84   TFilters filters = Self::_DLGetFilters( hnd );
85
86   // Save the loaded filters info
87   bool save_handler = false;
88   for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
89   {
90     // Check if the filter is completely new
91     auto act_catIt = this->m_Filters.find( catIt->first );
92     for(
93       auto clsIt = catIt->second.begin( );
94       clsIt != catIt->second.end( );
95       ++clsIt
96       )
97     {
98       bool new_filter = true;
99       if( act_catIt != this->m_Filters.end( ) )
100         new_filter =
101           ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
102
103       // Ok, it is new
104       if( new_filter )
105       {
106         // Update filters container
107         TCreator creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
108         if( creator != NULL )
109         {
110           this->m_DynFilters[ catIt->first][ *clsIt ] =
111             TDynFunc( canonical_fn, creator );
112           this->m_Filters[ catIt->first ].insert( *clsIt );
113           save_handler = true;
114
115         } // fi
116
117       } // fi
118
119     } // rof
120
121   } // rof
122
123   // Keep dynlib handler, if needed
124   if( save_handler )
125     this->m_DynLibraries[ canonical_fn ] = hnd;
126   else
127     Self::_DLClose( hnd );
128 }
129
130 // -------------------------------------------------------------------------
131 void cpPlugins::Interface::
132 UnloadAll( )
133 {
134   for(
135     auto d = this->m_DynLibraries.begin( );
136     d != this->m_DynLibraries.end( );
137     ++d
138     )
139     Self::_DLClose( d->second );
140   this->m_DynLibraries.clear( );
141   this->m_DynFilters.clear( );
142   this->m_Filters.clear( );
143 }
144
145 // -------------------------------------------------------------------------
146 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
147 Create( const std::string& category, const std::string& name )
148 {
149   cpPlugins::ProcessObject::Pointer filter = NULL;
150   auto catIt = this->m_DynFilters.find( category );
151   if( catIt != this->m_DynFilters.end( ) )
152   {
153     auto clsIt = catIt->second.find( name );
154     if( clsIt != catIt->second.end( ) )
155       filter = clsIt->second.second( );
156
157   } // fi
158   return( filter );
159 }
160
161 // -------------------------------------------------------------------------
162 void* cpPlugins::Interface::
163 _DLOpen( const std::string& fname )
164 {
165   void* hnd = NULL;
166 #ifdef cpPlugins_SYS_WINDOWS
167   hnd = ::LoadLibraryA( fname.c_str( ) );
168 #else // cpPlugins_SYS_WINDOWS
169   hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
170   dlerror( );
171 #endif // cpPlugins_SYS_WINDOWS
172   return( hnd );
173 }
174
175 // -------------------------------------------------------------------------
176 cpPlugins::Interface::
177 TFilters cpPlugins::Interface::
178 _DLGetFilters( void* hnd )
179 {
180   typedef const TFilters ( *f_t )( );
181
182   TFilters filters;
183 #ifdef cpPlugins_SYS_WINDOWS
184   auto f = ( f_t )(
185     ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" )
186     );
187   std::cout << f << std::endl;
188 #else // cpPlugins_SYS_WINDOWS
189   auto f = ( f_t ) dlsym( hnd, "cpPlugins_LoadedFilters" );
190   const char* err = dlerror( );
191   if( err != NULL )
192   {
193     dlclose( hnd );
194     throw std::runtime_error(
195       std::string(
196         "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
197         ) + std::string( err )
198       );
199
200   } // fi
201 #endif // cpPlugins_SYS_WINDOWS
202   filters = f( );
203   return( filters );
204 }
205
206 // -------------------------------------------------------------------------
207 cpPlugins::Interface::
208 TCreator cpPlugins::Interface::
209 _DLGetCreator(
210   void* hnd, const std::string& category, const std::string& name
211   )
212 {
213   TCreator c = NULL;
214   std::string func_name = category + "_" + name;
215 #ifdef cpPlugins_SYS_WINDOWS
216   // TODO:
217 #else // cpPlugins_SYS_WINDOWS
218   c = ( TCreator )dlsym( hnd, func_name.c_str( ) );
219   if( c == NULL )
220     throw std::runtime_error(
221       std::string( "cpPlugins::Interface: Class \"" ) +
222       category + std::string( ":" ) + name +
223       std::string( "\" does not have a valid creator function." )
224       );
225 #endif // cpPlugins_SYS_WINDOWS
226   return( c );
227 }
228
229 // -------------------------------------------------------------------------
230 void cpPlugins::Interface::
231 _DLClose( void* hnd )
232 {
233 #ifdef cpPlugins_SYS_WINDOWS
234   ::FreeLibrary( ( HMODULE )hnd );
235 #else // cpPlugins_SYS_WINDOWS
236   dlclose( hnd );
237 #endif // cpPlugins_SYS_WINDOWS
238 }
239
240 // eof - $RCSfile$