]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Interface.cxx
0ee1faf9911aea516acf2fbe49c3d57a7c744930
[cpPlugins.git] / lib / cpPlugins / Interface.cxx
1 #include <cpPlugins/Interface.h>
2
3 #ifdef cpPlugins_SYS_WINDOWS
4 #else // cpPlugins_SYS_WINDOWS
5 #  include <dlfcn.h>
6 #endif // cpPlugins_SYS_WINDOWS
7
8 // -------------------------------------------------------------------------
9 cpPlugins::Interface::
10 Interface( )
11 {
12 }
13
14 // -------------------------------------------------------------------------
15 cpPlugins::Interface::
16 ~Interface( )
17 {
18   this->UnloadAll( );
19 }
20
21 // -------------------------------------------------------------------------
22 const cpPlugins::Interface::
23 TFilters& cpPlugins::Interface::
24 GetFilters( )
25 {
26   return( this->m_Filters );
27 }
28
29 // -------------------------------------------------------------------------
30 void cpPlugins::Interface::
31 LoadPluginFile( const std::string& filename )
32 {
33   // Open library with its canonical path name
34   auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
35   void* hnd = Self::_DLOpen( canonical_fn );
36   if( hnd == NULL )
37     throw std::runtime_error(
38       std::string( "cpPlugins::Interface: Could not load library \"" ) +
39       canonical_fn +
40       std::string( "\"" )
41       );
42
43   // Load filters
44   TFilters filters = Self::_DLGetFilters( hnd );
45
46   // Save the loaded filters info
47   bool save_handler = false;
48   for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
49   {
50     // Check if the filter is completely new
51     auto act_catIt = this->m_Filters.find( catIt->first );
52     for(
53       auto clsIt = catIt->second.begin( );
54       clsIt != catIt->second.end( );
55       ++clsIt
56       )
57     {
58       bool new_filter = true;
59       if( act_catIt != this->m_Filters.end( ) )
60         new_filter =
61           ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
62
63       // Ok, it is new
64       if( new_filter )
65       {
66         // Update filters container
67         TCreator creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
68         if( creator != NULL )
69         {
70           this->m_DynFilters[ catIt->first][ *clsIt ] =
71             TDynFunc( canonical_fn, creator );
72           this->m_Filters[ catIt->first ].insert( *clsIt );
73           save_handler = true;
74
75         } // fi
76
77       } // fi
78
79     } // rof
80
81   } // rof
82
83   // Keep dynlib handler, if needed
84   if( save_handler )
85     this->m_DynLibraries[ canonical_fn ] = hnd;
86   else
87     Self::_DLClose( hnd );
88 }
89
90 // -------------------------------------------------------------------------
91 void cpPlugins::Interface::
92 UnloadAll( )
93 {
94   for(
95     auto d = this->m_DynLibraries.begin( );
96     d != this->m_DynLibraries.end( );
97     ++d
98     )
99     Self::_DLClose( d->second );
100   this->m_DynLibraries.clear( );
101   this->m_DynFilters.clear( );
102   this->m_Filters.clear( );
103 }
104
105 // -------------------------------------------------------------------------
106 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
107 Create( const std::string& category, const std::string& name )
108 {
109   cpPlugins::ProcessObject::Pointer filter = NULL;
110   auto catIt = this->m_DynFilters.find( category );
111   if( catIt != this->m_DynFilters.end( ) )
112   {
113     auto clsIt = catIt->second.find( name );
114     if( clsIt != catIt->second.end( ) )
115       filter = clsIt->second.second( );
116
117   } // fi
118   return( filter );
119 }
120
121 // -------------------------------------------------------------------------
122 void* cpPlugins::Interface::
123 _DLOpen( const std::string& fname )
124 {
125   void* hnd = NULL;
126 #ifdef cpPlugins_SYS_WINDOWS
127   // TODO:
128 #else // cpPlugins_SYS_WINDOWS
129   hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
130   dlerror( );
131 #endif // cpPlugins_SYS_WINDOWS
132   return( hnd );
133 }
134
135 // -------------------------------------------------------------------------
136 cpPlugins::Interface::
137 TFilters cpPlugins::Interface::
138 _DLGetFilters( void* hnd )
139 {
140   TFilters filters;
141 #ifdef cpPlugins_SYS_WINDOWS
142   // TODO:
143 #else // cpPlugins_SYS_WINDOWS
144   typedef const TFilters ( *f_t )( );
145   auto f = ( f_t ) dlsym( hnd, "cpPlugins_LoadedFilters" );
146   const char* err = dlerror( );
147   if( err != NULL )
148   {
149     dlclose( hnd );
150     throw std::runtime_error(
151       std::string(
152         "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
153         ) + std::string( err )
154       );
155
156   } // fi
157   filters = f( );
158 #endif // cpPlugins_SYS_WINDOWS
159   return( filters );
160 }
161
162 // -------------------------------------------------------------------------
163 cpPlugins::Interface::
164 TCreator cpPlugins::Interface::
165 _DLGetCreator(
166   void* hnd, const std::string& category, const std::string& name
167   )
168 {
169   TCreator c = NULL;
170   std::string func_name = category + "_" + name;
171 #ifdef cpPlugins_SYS_WINDOWS
172   // TODO:
173 #else // cpPlugins_SYS_WINDOWS
174   c = ( TCreator )dlsym( hnd, func_name.c_str( ) );
175   if( c == NULL )
176     throw std::runtime_error(
177       std::string( "cpPlugins::Interface: Class \"" ) +
178       category + std::string( ":" ) + name +
179       std::string( "\" does not have a valid creator function." )
180       );
181 #endif // cpPlugins_SYS_WINDOWS
182   return( c );
183 }
184
185 // -------------------------------------------------------------------------
186 void cpPlugins::Interface::
187 _DLClose( void* hnd )
188 {
189 #ifdef cpPlugins_SYS_WINDOWS
190   // TODO:
191 #else // cpPlugins_SYS_WINDOWS
192   dlclose( hnd );
193 #endif // cpPlugins_SYS_WINDOWS
194 }
195
196 // eof - $RCSfile$