b4adda843d97f2092451e7714e8aeecabfcfed74
[occt.git] / src / OSD / OSD_SharedLibrary.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _WIN32
16
17
18 #include <OSD_Function.hxx>
19 #include <OSD_LoadMode.hxx>
20 #include <OSD_SharedLibrary.hxx>
21
22 #include <stdio.h>
23 #ifdef __some_crappy_system__
24 /*
25  * Values for 'mode' argument in dlopen().
26  *
27 */
28 #define RTLD_LAZY               1
29 #define RTLD_NOW                2
30 /*
31  * Interface to rld via unsupported __rld_libdl_interface() call.
32  *
33  */
34 #define _LIBDL_RLD_DLOPEN       1
35 #define _LIBDL_RLD_DLCLOSE      2
36 #define _LIBDL_RLD_DLSYM        3
37 #define _LIBDL_RLD_DLERROR      4
38 extern "C" {void        *dlopen(char *path, int mode);}
39 extern "C" {void*   dlsym   (       void*  handle,char* name);}
40 extern "C" {int     dlclose (       void  *handle  );}
41 extern "C" {void    *dlerror (void);}
42 #endif
43
44 #include <dlfcn.h>
45
46 #define BAD(X)  ((X) == NULL)
47
48 // ----------------------------------------------------------------
49 //
50 // Create and initialize a shared library object to NULL
51 //
52 // ----------------------------------------------------------------
53 OSD_SharedLibrary::OSD_SharedLibrary():myHandle(NULL),myName(NULL){
54 }
55 // ----------------------------------------------------------------
56 //
57 // Create and initialize a shared library object to the
58 // name given as argument
59 //
60 // ----------------------------------------------------------------
61 OSD_SharedLibrary::OSD_SharedLibrary(const Standard_CString aName):myHandle(NULL) 
62 {
63   if (aName != NULL) {
64     myName = new char [(strlen (aName) + 1 )];
65     strcpy (myName,aName);
66   }
67 }
68 // ----------------------------------------------------------------
69 //
70 // Name: Returns the shared library name
71 //
72 // ----------------------------------------------------------------
73 Standard_CString  OSD_SharedLibrary::Name() const {
74   return myName; 
75 }
76 // ----------------------------------------------------------------
77 //
78 // SetName: Sets a name to a shared library object
79 //
80 // ----------------------------------------------------------------
81 void  OSD_SharedLibrary::SetName(const Standard_CString aName)  {
82   if (aName != NULL) {
83     myName = new char [(strlen (aName) + 1 )];
84     strcpy (myName,aName);
85   }
86 }
87 // ----------------------------------------------------------------
88 //
89 // DlOpen:   The dlopen function provides an interface to the dynamic 
90 // library loader to allow shared libraries to be loaded and called at
91 // runtime.  
92 // The dlopen function attempts to load filename, in the address space 
93 // of the process, resolving symbols as appropriate.  Any libraries that      
94 // filename depends upon are also loaded.
95 //
96 // If mode is RTLD_LAZY, then the runtime loader does symbol resolution 
97 // only as needed.  Typically, this means that the first call   
98 // to a function in the newly loaded library will cause the resolution 
99 // of the address of that function to occur.  
100 //
101 // If mode is RTLD_NOW, then the runtime loader must do all
102 // symbol binding during the dlopen call.  
103 // The dlopen function returns a handle that is used by dlsym or 
104 // dlclose call.  If there is an error, a NULLpointer is returned.
105 //
106 // If a NULL filename is specified, dlopen returns a handle for the main      
107 // executable, which allows access to dynamic symbols in the running program.
108 //
109 // ----------------------------------------------------------------
110 Standard_Boolean  OSD_SharedLibrary::DlOpen(const OSD_LoadMode aMode ) {
111 if (aMode == OSD_RTLD_LAZY){
112   myHandle = dlopen (myName,RTLD_LAZY);
113 }
114 else if (aMode == OSD_RTLD_NOW){
115   myHandle = dlopen (myName,RTLD_NOW);
116 }
117
118 if (!BAD(myHandle)){
119   return Standard_True;
120  }
121 else {
122   return Standard_False;
123  }
124 }
125 // ----------------------------------------------------------------
126 //
127 // DlSymb: The dlsym function returns the address of the        
128 // symbol name found in the shared library corresponding to handle.  
129 // If the symbol is not found, a NULL
130 // pointer is returned.
131 //
132 // ----------------------------------------------------------------
133 OSD_Function  OSD_SharedLibrary::DlSymb(const Standard_CString aName )const{
134 void (*fp)();
135 fp =  (void (*)()) dlsym (myHandle,aName);
136 if (!BAD(fp)){
137   return (OSD_Function)fp;
138  }
139 else {
140   return (OSD_Function)NULL;
141  }
142 }
143 // ----------------------------------------------------------------
144 //
145 //DlClose: The dlclose function deallocates the address space for the library
146 //corresponding to handle.  If any user function continues to call a symbol
147 //resolved in the address space of a library that has been since been deallo-
148 //cated by dlclose, the results are undefined.
149 //
150 // ----------------------------------------------------------------
151 void OSD_SharedLibrary::DlClose()const{
152  dlclose(myHandle);
153 }
154 // ----------------------------------------------------------------
155 //
156 // DlError:  returns a string   describing the last error that
157 // occurred from a call to dlopen, dlclose or dlsym.
158 //
159 // ----------------------------------------------------------------
160 Standard_CString OSD_SharedLibrary::DlError()const{
161 return (char*) dlerror();
162 }
163 // ----------------------------------------------------------------------------
164 // Destroy
165 // ----------------------------------------------------------------------------
166 void OSD_SharedLibrary::Destroy() {
167   if (myName != NULL) {
168      delete [] myName;
169      myName = NULL;
170      myHandle = NULL;
171   }
172 }
173
174 #else
175
176 //------------------------------------------------------------------------
177 //-------------------  Windows NT sources for OSD_SharedLibrary ----------
178 //------------------------------------------------------------------------
179
180 //it is important to define STRICT and enforce including <windows.h> before
181 //Standard_Macro.hxx undefines it and includes <windows.h> causing compilation errors
182 #ifndef STRICT
183 #define STRICT
184 #endif
185 #include <windows.h>
186
187 #include <OSD_Path.hxx>
188 #include <OSD_SharedLibrary.hxx>
189 #include <TCollection_AsciiString.hxx>
190 #include <TCollection_ExtendedString.hxx>
191
192 #include <Standard_WarningDisableFunctionCast.hxx>
193
194 static DWORD              lastDLLError;
195
196 static wchar_t errMsg[1024];
197 static char errMsgA[1024];
198
199 OSD_SharedLibrary :: OSD_SharedLibrary () {
200
201  myHandle = NULL;
202  myName   = NULL;
203
204 }  // end constructor ( 1 )
205
206 OSD_SharedLibrary :: OSD_SharedLibrary ( const Standard_CString aFilename ) {
207
208  myHandle = NULL;
209  myName   = NULL;
210
211  SetName ( aFilename );
212
213 }  // end constructro ( 2 )
214
215 void OSD_SharedLibrary :: SetName ( const Standard_CString aName ) {
216
217  OSD_Path                path ( aName );
218  TCollection_AsciiString name ( aName );
219
220  if ( myName != NULL )
221
222   delete [] myName;
223
224  myName = new Standard_Character[ strlen ( aName ) + 1 ];
225
226  strcpy ( myName, aName );
227
228  name = path.Name ();
229  name.AssignCat (  path.Extension ()  );
230
231  TCollection_ExtendedString nameW (name);
232 #ifndef OCCT_UWP
233  myHandle = GetModuleHandleW (nameW.ToWideString());
234 #else
235  myHandle = LoadPackagedLibrary (nameW.ToWideString(), NULL);
236  FreeLibrary ((HMODULE) myHandle);
237 #endif
238
239 }  // end OSD_SharedLibrary :: SetName
240
241 Standard_CString OSD_SharedLibrary :: Name () const {
242
243  return myName;
244
245 }  // end OSD_SharedLibrary :: Name
246
247 Standard_Boolean OSD_SharedLibrary :: DlOpen ( const OSD_LoadMode /*Mode*/ ) {
248
249  Standard_Boolean retVal = Standard_True;
250
251  if (myHandle == NULL)
252  {
253   TCollection_ExtendedString myNameW (myName);
254 #ifndef OCCT_UWP
255   myHandle = (HINSTANCE)LoadLibraryExW (myNameW.ToWideString(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
256 #else
257   myHandle = (HINSTANCE)LoadPackagedLibrary (myNameW.ToWideString(), NULL);
258 #endif
259   if ( myHandle == NULL ) {
260    lastDLLError = GetLastError ();
261    retVal       = Standard_False;
262   }
263  }  // end if
264
265  return retVal;
266
267 }  // end OSD_SharedLibrary :: DlOpen
268
269 OSD_Function OSD_SharedLibrary :: DlSymb ( const Standard_CString Name ) const {
270
271  OSD_Function func = ( OSD_Function )GetProcAddress (  ( HMODULE )myHandle, Name  );
272
273  if ( func == NULL )
274
275   lastDLLError = GetLastError ();
276
277  return func;
278
279 }  // end OSD_SharedLibrary :: DlSymb
280
281 void OSD_SharedLibrary :: DlClose () const {
282
283  FreeLibrary (  ( HMODULE )myHandle  );
284
285 }  // end OSD_SharedLibrary :: DlClose
286
287 Standard_CString OSD_SharedLibrary :: DlError () const {
288
289  FormatMessageW (
290   FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
291   0, lastDLLError, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
292    errMsg, 1024, ( va_list* )&myName
293  );
294
295  WideCharToMultiByte(CP_UTF8, 0, errMsg, -1, errMsgA, sizeof(errMsgA), NULL, NULL);
296  return errMsgA;
297 }  // end OSD_SharedLibrary :: DlError
298
299 void OSD_SharedLibrary :: Destroy () {
300
301  if ( myName != NULL ) delete [] myName;
302
303 }  // end OSD_SharedLibrary :: Destroy
304
305 #endif