]> git.saurik.com Git - wxWidgets.git/blob - src/common/dynlib.cpp
fix for HP-UX
[wxWidgets.git] / src / common / dynlib.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dynlib.cpp
3 // Purpose: Dynamic library management
4 // Author: Guilhem Lavaux
5 // Modified by:
6 // Created: 20/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 # pragma implementation "dynlib.h"
22 #endif
23
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29 #if wxUSE_DYNLIB_CLASS
30
31 #include "wx/dynlib.h"
32 #include "wx/filefn.h"
33 #include "wx/intl.h"
34 #include "wx/log.h"
35 #include "wx/tokenzr.h"
36
37 // ----------------------------------------------------------------------------
38 // conditional compilation
39 // ----------------------------------------------------------------------------
40
41 #if defined(HAVE_DLOPEN)
42 # define wxDllOpen(lib) dlopen(lib.fn_str(), RTLD_NOW/*RTLD_LAZY*/)
43 # define wxDllGetSymbol(handle, name) dlsym(handle, name.mb_str())
44 # define wxDllClose dlclose
45 #elif defined(HAVE_SHL_LOAD)
46 # define wxDllOpen(lib) shl_load(lib.fn_str(), BIND_DEFERRED, 0)
47 # define wxDllClose shl_unload
48
49 static inline void *wxDllGetSymbol(shl_t handle, const wxString& name)
50 {
51 void *sym;
52 if ( shl_findsym(&handle, name.mb_str(), TYPE_UNDEFINED, &sym) == 0 )
53 return sym;
54 else
55 return (void *)0;
56 }
57 #elif defined(__WINDOWS__)
58 # include <windows.h>
59
60 // using LoadLibraryEx under Win32 to avoid name clash with LoadLibrary
61 # ifdef __WIN32__
62 # define wxDllOpen(lib) ::LoadLibraryEx(lib, 0, 0)
63 # else // Win16
64 # define wxDllOpen(lib) ::LoadLibrary(lib)
65 # endif // Win32/16
66 # define wxDllGetSymbol(handle, name) ::GetProcAddress(handle, name)
67 # define wxDllClose ::FreeLibrary
68
69 #elif defined(__OS2__)
70
71 # define INCL_DOS
72 # include <os2.h>
73 # define wxDllOpen(error, lib, handle) DosLoadModule(error, sizeof(error), lib, &handle)
74 # define wxDllGetSymbol(handle, modaddr) DosQueryProcAddr(handle, 1L, NULL, (PFN*)modaddr)
75 # define wxDllClose(handle) DosFreeModule(handle)
76 #else
77 # error "Don't know how to load shared libraries on this platform."
78 #endif // OS
79
80 // ---------------------------------------------------------------------------
81 // Global variables
82 // ---------------------------------------------------------------------------
83
84 wxLibraries wxTheLibraries;
85
86 // ----------------------------------------------------------------------------
87 // private functions
88 // ----------------------------------------------------------------------------
89
90 // construct the full name from the base shared object name: adds a .dll
91 // suffix under Windows or .so under Unix
92 static wxString ConstructLibraryName(const wxString& basename)
93 {
94 wxString fullname(basename);
95
96 #if defined(__UNIX__)
97 # if defined(__HPUX__)
98 fullname << ".sl";
99 # else //__HPUX__
100 fullname << ".so";
101 # endif //__HPUX__
102 #elif defined(__WINDOWS__) || defined(__OS2__)
103 fullname << ".dll";
104 #endif
105
106 return fullname;
107 }
108
109 // ============================================================================
110 // implementation
111 // ============================================================================
112
113
114 // ---------------------------------------------------------------------------
115 // wxLibrary (one instance per dynamic library)
116 // ---------------------------------------------------------------------------
117
118 wxLibrary::wxLibrary(wxDllType handle)
119 {
120 typedef wxClassInfo *(*t_get_first)(void);
121 t_get_first get_first;
122
123 m_handle = handle;
124
125 // Some system may use a local heap for library.
126 get_first = (t_get_first)GetSymbol("wxGetClassFirst");
127 // It is a wxWindows DLL.
128 if (get_first)
129 PrepareClasses(get_first());
130 }
131
132 wxLibrary::~wxLibrary()
133 {
134 if ( m_handle )
135 {
136 wxDllClose(m_handle);
137 }
138 }
139
140 wxObject *wxLibrary::CreateObject(const wxString& name)
141 {
142 wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
143
144 if (!info)
145 return NULL;
146
147 return info->CreateObject();
148 }
149
150 void wxLibrary::PrepareClasses(wxClassInfo *first)
151 {
152 // Index all class infos by their class name
153 wxClassInfo *info = first;
154 while (info)
155 {
156 if (info->m_className)
157 classTable.Put(info->m_className, (wxObject *)info);
158 info = info->GetNext();
159 }
160
161 // Set base pointers for each wxClassInfo
162 info = first;
163 while (info)
164 {
165 if (info->GetBaseClassName1())
166 info->m_baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
167 if (info->GetBaseClassName2())
168 info->m_baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
169 info = info->m_next;
170 }
171 }
172
173 void *wxLibrary::GetSymbol(const wxString& symbname)
174 {
175 return wxDllLoader::GetSymbol(m_handle, symbname);
176 }
177
178 // ---------------------------------------------------------------------------
179 // wxDllLoader
180 // ---------------------------------------------------------------------------
181
182 /* static */
183 wxDllType
184 wxDllLoader::GetProgramHandle(void)
185 {
186 #if defined( HAVE_DLOPEN )
187 // optain handle for main program
188 return dlopen(NULL, RTLD_NOW/*RTLD_LAZY*/);
189 #elif defined (HAVE_SHL_LOAD)
190 // shl_findsymbol with NULL handle looks up in main program
191 return 0;
192 #else
193 #warning "Please implement this for your system!"
194 wxFAIL_MSG(_("This method is not implemented under Windows or OS/2"));
195 return 0;
196 #endif
197 }
198
199 /* static */
200 wxDllType
201 wxDllLoader::LoadLibrary(const wxString & libname, bool *success)
202 {
203 wxDllType handle;
204
205 #if defined(__WXMAC__)
206 FSSpec myFSSpec ;
207 Ptr myMainAddr ;
208 Str255 myErrName ;
209
210 wxMacPathToFSSpec( libname , &myFSSpec ) ;
211 if (GetDiskFragment( &myFSSpec , 0 , kCFragGoesToEOF , "\p" , kPrivateCFragCopy , &handle , &myMainAddr ,
212 myErrName ) != noErr )
213 {
214 p2cstr( myErrName ) ;
215 wxASSERT_MSG( 1 , (char*)myErrName ) ;
216 return NULL ;
217 }
218 #elif defined(__OS2__)
219 char zError[256] = "";
220 wxDllOpen(zError, libname, handle);
221 #else // !Mac
222 handle = wxDllOpen(libname);
223 #endif // OS
224
225 if ( !handle )
226 {
227 wxLogSysError(_("Failed to load shared library '%s'"), libname.c_str());
228 }
229
230 if ( success )
231 {
232 *success = handle != 0;
233 }
234
235 return handle;
236 }
237
238
239 /* static */
240 void
241 wxDllLoader::UnloadLibrary(wxDllType handle)
242 {
243 wxDllClose(handle);
244 }
245
246 /* static */
247 void *
248 wxDllLoader::GetSymbol(wxDllType dllHandle, const wxString &name)
249 {
250 void *symbol = NULL; // return value
251
252 #if defined( __WXMAC__ )
253 Ptr symAddress ;
254 CFragSymbolClass symClass ;
255 Str255 symName ;
256
257 strcpy( (char*) symName , name ) ;
258 c2pstr( (char*) symName ) ;
259
260 if ( FindSymbol( dllHandle , symName , &symAddress , &symClass ) == noErr )
261 symbol = (void *)symAddress ;
262 #elif defined( __OS2__ )
263 wxDllGetSymbol(dllHandle, symbol);
264 #else
265 symbol = wxDllGetSymbol(dllHandle, name);
266 #endif
267
268 if ( !symbol )
269 {
270 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
271 name.c_str());
272 }
273 return symbol;
274 }
275
276 // ---------------------------------------------------------------------------
277 // wxLibraries (only one instance should normally exist)
278 // ---------------------------------------------------------------------------
279
280 wxLibraries::wxLibraries()
281 {
282 }
283
284 wxLibraries::~wxLibraries()
285 {
286 wxNode *node = m_loaded.First();
287
288 while (node) {
289 wxLibrary *lib = (wxLibrary *)node->Data();
290 delete lib;
291
292 node = node->Next();
293 }
294 }
295
296 wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
297 {
298 wxNode *node;
299 wxLibrary *lib;
300 wxClassInfo *old_sm_first;
301
302 #if defined(__VISAGECPP__)
303 node = m_loaded.Find(name.GetData());
304 if (node != NULL)
305 return ((wxLibrary *)node->Data());
306 #else // !OS/2
307 if ( (node = m_loaded.Find(name.GetData())) )
308 return ((wxLibrary *)node->Data());
309 #endif
310 // If DLL shares data, this is necessary.
311 old_sm_first = wxClassInfo::sm_first;
312 wxClassInfo::sm_first = NULL;
313
314 wxString libname = ConstructLibraryName(name);
315
316 /*
317 Unix automatically builds that library name, at least for dlopen()
318 */
319 #if 0
320 #if defined(__UNIX__)
321 // found the first file in LD_LIBRARY_PATH with this name
322 wxString libPath("/lib:/usr/lib"); // system path first
323 const char *envLibPath = getenv("LD_LIBRARY_PATH");
324 if ( envLibPath )
325 libPath << ':' << envLibPath;
326 wxStringTokenizer tokenizer(libPath, _T(':'));
327 while ( tokenizer.HasMoreToken() )
328 {
329 wxString fullname(tokenizer.NextToken());
330
331 fullname << '/' << libname;
332 if ( wxFileExists(fullname) )
333 {
334 libname = fullname;
335
336 // found the library
337 break;
338 }
339 }
340 //else: not found in the path, leave the name as is (secutiry risk?)
341
342 #endif // __UNIX__
343 #endif
344
345 bool success = FALSE;
346 wxDllType handle = wxDllLoader::LoadLibrary(libname, &success);
347 if(success)
348 {
349 lib = new wxLibrary(handle);
350 wxClassInfo::sm_first = old_sm_first;
351 m_loaded.Append(name.GetData(), lib);
352 }
353 else
354 lib = NULL;
355 return lib;
356 }
357
358 wxObject *wxLibraries::CreateObject(const wxString& path)
359 {
360 wxNode *node = m_loaded.First();
361 wxObject *obj;
362
363 while (node) {
364 obj = ((wxLibrary *)node->Data())->CreateObject(path);
365 if (obj)
366 return obj;
367
368 node = node->Next();
369 }
370 return NULL;
371 }
372
373 #endif // wxUSE_DYNLIB_CLASS