]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/OS/DLLManager.cxx
c8024c0d088fe8d225d01d1c1a6c2b9f81cb3c71
[cpPlugins.git] / lib / cpPlugins / OS / DLLManager.cxx
1 #include <cpPlugins/OS/DLLManager.h>
2 #include <cpPlugins/Utility.h>
3 #include <queue>
4 #ifdef cpPlugins_OS_Windows
5 #  include <Windows.h>
6 #else // cpPlugins_OS_Windows
7 #  include <dlfcn.h>
8 #endif // cpPlugins_OS_Windows
9
10 // -------------------------------------------------------------------------
11 void cpPlugins::OS::DLLManager::
12 TeaseLoadedLibraries( )
13 {
14   void* hnd = cpPlugins::OS::DLLManager::_Load( "", 0 );
15   if( hnd == NULL )
16     throw std::runtime_error( "Something really nasty just happened." );
17 }
18
19 // -------------------------------------------------------------------------
20 void cpPlugins::OS::DLLManager::
21 GetPluginsLibraryContents(
22   std::map< std::string, std::set< std::string > >& filters,
23   const std::string& libname
24   )
25 {
26   typedef const char* ( *_TFunction )( );
27
28   // Load library
29   void* hnd = cpPlugins::OS::DLLManager::_Load( libname, RTLD_LAZY );
30   if( hnd == NULL )
31     throw std::runtime_error( "Something nasty just happened." );
32
33   // Get library contents
34   filters.clear( );
35   _TFunction descriptors_func = NULL;
36   try
37   {
38     descriptors_func =
39       reinterpret_cast< _TFunction >(
40       cpPlugins::OS::DLLManager::_Sym( hnd, "cpPlugins_LoadedFilters" )
41       );
42   }
43   catch( ... ) { }
44   if( descriptors_func != NULL )
45   {
46     std::string descriptors = descriptors_func( );
47     std::vector< std::string > tokens;
48     cpPlugins::Tokenize( tokens, descriptors, ";" );
49     for( auto t : tokens )
50     {
51       std::size_t pos = t.find( ":" );
52       filters[ t.substr( 0, pos ) ].insert( t.substr( pos + 1 ) );
53
54     } // rof
55     cpPlugins::OS::DLLManager::_UnLoad( hnd );
56   }
57   else
58   {
59     cpPlugins::OS::DLLManager::_UnLoad( hnd );
60     throw std::runtime_error( 
61       std::string( "Library \"" ) +
62       libname +
63       std::string( "\" not recognized as a cpPlugins library" )
64       );
65
66   } // fi
67 }
68
69 // -------------------------------------------------------------------------
70 void* cpPlugins::OS::DLLManager::
71 LoadPlugins( const std::string& lname )
72 {
73   return( cpPlugins::OS::DLLManager::_Load( lname, RTLD_NOW | RTLD_GLOBAL ) );
74 }
75
76 // -------------------------------------------------------------------------
77 void* cpPlugins::OS::DLLManager::
78 LoadCreator(
79   void* lib_hnd, const std::string& category, const std::string& name
80   )
81 {
82   return(
83     cpPlugins::OS::DLLManager::_Sym(
84       lib_hnd, ( category + "_" + name ).c_str( )
85       )
86     );
87 }
88
89 // -------------------------------------------------------------------------
90 #ifdef cpPlugins_OS_Windows
91 #else // cpPlugins_OS_Windows
92 namespace cpPlugins
93 {
94   namespace OS
95   {
96     /**
97      */
98     struct link_struct
99     {
100       void* pointers[ 3 ];
101       struct link_struct* ptr;
102     };
103
104     /**
105      */
106     struct link_map
107     {
108       void* address;
109       char* path;
110       void* not_needed;
111       struct link_map* next;
112       struct link_map* prev;
113     };
114
115   } // ecapseman
116
117 } // ecapseman
118 #endif // cpPlugins_OS_Windows
119
120 // -------------------------------------------------------------------------
121 void* cpPlugins::OS::DLLManager::
122 _Load( const std::string& libname, int flags )
123 {
124   void* return_handle = NULL;
125
126 #ifdef cpPlugins_OS_Windows
127 #else // cpPlugins_OS_Windows
128   std::queue< std::string > q;
129   std::set< std::string > m;
130   q.push( libname );
131   while( !q.empty( ) )
132   {
133     // Get next filename
134     std::string lname = q.front( );
135     q.pop( );
136     if( m.find( lname ) != m.end( ) )
137       continue;
138
139     // Get library handle (main program vs. linked libraries)
140     void* h = NULL;
141     if( lname != "" )
142     {
143       if( lname == libname )
144       {
145         h = dlopen( lname.c_str( ), flags );
146         return_handle = h;
147       }
148       else
149         h = dlopen( lname.c_str( ), RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE );
150     }
151     else
152     {
153       h = dlopen( NULL, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE );
154       return_handle = h;
155
156     } // fi
157     char* err = dlerror( );
158     if( err != NULL )
159       throw std::runtime_error( err );
160
161     // Process data
162     if( h != NULL )
163     {
164       link_struct* p = reinterpret_cast< link_struct* >( h )->ptr;
165       if( p != NULL )
166       {
167         m.insert( lname );
168         link_map* m = reinterpret_cast< link_map* >( p->ptr );
169         while( m != NULL )
170         {
171           q.push( m->path );
172           m = m->next;
173
174         } // elihw
175
176       } // fi
177
178     } // fi
179
180   } // elihw
181 #endif // cpPlugins_OS_Windows
182   return( return_handle );
183 }
184
185 // -------------------------------------------------------------------------
186 void* cpPlugins::OS::DLLManager::
187 _Sym( void* hnd, const std::string& symname )
188 {
189   void* s = NULL;
190 #ifdef cpPlugins_OS_Windows
191 #else // cpPlugins_OS_Windows
192   s = dlsym( hnd, symname.c_str( ) );
193   char* err = dlerror( );
194   if( err != NULL )
195     throw std::runtime_error( err );
196 #endif // cpPlugins_OS_Windows
197   return( s );
198 }
199
200 // -------------------------------------------------------------------------
201 void cpPlugins::OS::DLLManager::
202 _UnLoad( void* hnd )
203 {
204 #ifdef cpPlugins_OS_Windows
205 #else // cpPlugins_OS_Windows
206   if( hnd != NULL )
207   {
208     dlclose( hnd );
209     char* err = dlerror( );
210     if( err != NULL )
211       throw std::runtime_error( err );
212
213   } // fi
214 #endif // cpPlugins_OS_Windows
215 }
216
217 /* TODO
218    void* cpPlugins::OS::DLLManager::
219    Load( const std::string& fname, std::string& error )
220    {
221    void* hnd = NULL;
222    #ifdef cpPlugins_OS_Windows
223    UINT old = ::SetErrorMode( SEM_FAILCRITICALERRORS );
224    ::SetErrorMode( old | SEM_FAILCRITICALERRORS );
225    hnd = ::LoadLibraryA( fname.c_str( ) );
226    ::SetErrorMode( old );
227    if( hnd == NULL )
228    error = "Could not load library.";
229    #else // cpPlugins_OS_Windows
230    hnd = dlopen( fname.c_str( ), RTLD_LAZY | RTLD_GLOBAL );
231    if( hnd == NULL )
232    error = dlerror( );
233    else
234    dlerror( );
235    #endif // cpPlugins_OS_Windows
236    return( hnd );
237    }
238
239    // -------------------------------------------------------------------------
240    void cpPlugins::OS::DLLManager::
241    UnLoad( void* hnd )
242    {
243    #ifdef cpPlugins_OS_Windows
244    ::FreeLibrary( ( HMODULE )hnd );
245    #else // cpPlugins_OS_Windows
246    dlclose( hnd );
247    #endif // cpPlugins_OS_Windows
248    }
249
250    // -------------------------------------------------------------------------
251    void* cpPlugins::OS::DLLManager::
252    GetFunctionHandle( void* hnd, const std::string& function )
253    {
254    void* f = NULL;
255    if( hnd != NULL )
256    {
257    #ifdef cpPlugins_OS_Windows
258    f = ::GetProcAddress( ( HMODULE )hnd, function.c_str( ) );
259    #else // cpPlugins_OS_Windows
260    f = dlsym( hnd, function.c_str( ) );
261    #endif // cpPlugins_OS_Windows
262    } // fi
263    return( f );
264    }
265 */
266
267 // eof - $RCSfile$