]> git.saurik.com Git - wxWidgets.git/blame - src/common/dynlib.cpp
OS/2 fixes for this week.
[wxWidgets.git] / src / common / dynlib.cpp
CommitLineData
7a4b9130
GL
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
7b0bfbb2
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
7a4b9130 20#ifdef __GNUG__
a585ca5c 21# pragma implementation "dynlib.h"
7a4b9130
GL
22#endif
23
0c32066b
JS
24#include "wx/wxprec.h"
25
2df7be7f
RR
26#ifdef __BORLANDC__
27 #pragma hdrstop
28#endif
f6bcfd97 29
8a0d4cf6
VZ
30#if wxUSE_DYNLIB_CLASS
31
f6bcfd97
BP
32#if defined(__WINDOWS__)
33 #include "wx/msw/private.h"
34#endif
35
7b0bfbb2
VZ
36#include "wx/dynlib.h"
37#include "wx/filefn.h"
38#include "wx/intl.h"
39#include "wx/log.h"
8a0d4cf6 40#include "wx/tokenzr.h"
7b0bfbb2
VZ
41
42// ----------------------------------------------------------------------------
43// conditional compilation
44// ----------------------------------------------------------------------------
45
1a787c5d
SN
46#if defined(__WXPM__) || defined(__EMX__)
47# define INCL_DOS
48# include <os2.h>
49# define wxDllOpen(error, lib, handle) DosLoadModule(error, sizeof(error), lib, &handle)
50# define wxDllGetSymbol(handle, modaddr) DosQueryProcAddr(handle, 1L, NULL, (PFN*)modaddr)
51# define wxDllClose(handle) DosFreeModule(handle)
52#elif defined(HAVE_DLOPEN)
237c5c02
VZ
53 // note about dlopen() flags: we use RTLD_NOW to have more Windows-like
54 // behaviour (Win won't let you load a library with missing symbols) and
55 // RTLD_GLOBAL because it is needed sometimes and probably doesn't hurt
343a06a5
JJ
56 // otherwise. On True64-Unix RTLD_GLOBAL is not allowed and on VMS the
57 // second argument on dlopen is ignored.
99d96a2b
JJ
58#ifdef __VMS
59# define wxDllOpen(lib) dlopen(lib.fn_str(), 0 )
343a06a5
JJ
60#elif defined( __osf__ )
61# define wxDllOpen(lib) dlopen(lib.fn_str(), RTLD_LAZY )
99d96a2b
JJ
62#else
63# define wxDllOpen(lib) dlopen(lib.fn_str(), RTLD_LAZY | RTLD_GLOBAL)
64#endif
65#define wxDllGetSymbol(handle, name) dlsym(handle, name)
a585ca5c 66# define wxDllClose dlclose
8a0d4cf6 67#elif defined(HAVE_SHL_LOAD)
a585ca5c 68# define wxDllOpen(lib) shl_load(lib.fn_str(), BIND_DEFERRED, 0)
237c5c02 69# define wxDllClose shl_unload
846e1424 70
50920146 71 static inline void *wxDllGetSymbol(shl_t handle, const wxString& name)
7b0bfbb2
VZ
72 {
73 void *sym;
50920146 74 if ( shl_findsym(&handle, name.mb_str(), TYPE_UNDEFINED, &sym) == 0 )
7b0bfbb2
VZ
75 return sym;
76 else
77 return (void *)0;
78 }
03e11df5 79#elif defined(__APPLE__) && defined(__UNIX__)
4c27c3c6
GD
80void *dlopen(const char *path, int mode /* mode is ignored */);
81void *dlsym(void *handle, const char *symbol);
03e11df5 82int dlclose(void *handle);
4c27c3c6 83const char *dlerror(void);
03e11df5
GD
84
85# define wxDllOpen(lib) dlopen(lib.fn_str(), 0)
86# define wxDllGetSymbol(handle, name) dlsym(handle, name)
87# define wxDllClose dlclose
7b0bfbb2 88#elif defined(__WINDOWS__)
90022ddc 89 // using LoadLibraryEx under Win32 to avoid name clash with LoadLibrary
a585ca5c 90# ifdef __WIN32__
f6bcfd97
BP
91#ifdef _UNICODE
92# define wxDllOpen(lib) ::LoadLibraryExW(lib, 0, 0)
93#else
94# define wxDllOpen(lib) ::LoadLibraryExA(lib, 0, 0)
95#endif
a585ca5c
KB
96# else // Win16
97# define wxDllOpen(lib) ::LoadLibrary(lib)
98# endif // Win32/16
99# define wxDllGetSymbol(handle, name) ::GetProcAddress(handle, name)
100# define wxDllClose ::FreeLibrary
763ca781
SC
101#elif defined(__WXMAC__)
102# define wxDllClose(handle) CloseConnection(&handle)
7b0bfbb2 103#else
a585ca5c 104# error "Don't know how to load shared libraries on this platform."
7b0bfbb2 105#endif // OS
7a4b9130
GL
106
107// ---------------------------------------------------------------------------
7b0bfbb2 108// Global variables
7a4b9130
GL
109// ---------------------------------------------------------------------------
110
7b0bfbb2 111wxLibraries wxTheLibraries;
7a4b9130 112
f6bcfd97
BP
113// ============================================================================
114// implementation
115// ============================================================================
123a7fdd 116
7b0bfbb2
VZ
117// construct the full name from the base shared object name: adds a .dll
118// suffix under Windows or .so under Unix
119static wxString ConstructLibraryName(const wxString& basename)
120{
f6bcfd97
BP
121 wxString fullname;
122 fullname << basename << wxDllLoader::GetDllExt();
27529614 123
7b0bfbb2
VZ
124 return fullname;
125}
7a4b9130 126
7a4b9130 127// ---------------------------------------------------------------------------
7b0bfbb2 128// wxLibrary (one instance per dynamic library)
7a4b9130
GL
129// ---------------------------------------------------------------------------
130
7b0bfbb2 131wxLibrary::wxLibrary(wxDllType handle)
7a4b9130 132{
7b0bfbb2
VZ
133 typedef wxClassInfo *(*t_get_first)(void);
134 t_get_first get_first;
7a4b9130 135
7b0bfbb2 136 m_handle = handle;
7a4b9130 137
7b0bfbb2
VZ
138 // Some system may use a local heap for library.
139 get_first = (t_get_first)GetSymbol("wxGetClassFirst");
140 // It is a wxWindows DLL.
141 if (get_first)
142 PrepareClasses(get_first());
7a4b9130
GL
143}
144
145wxLibrary::~wxLibrary()
146{
7b0bfbb2
VZ
147 if ( m_handle )
148 {
149 wxDllClose(m_handle);
150 }
7a4b9130
GL
151}
152
153wxObject *wxLibrary::CreateObject(const wxString& name)
154{
7b0bfbb2 155 wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
f4a8c29f 156
7b0bfbb2
VZ
157 if (!info)
158 return NULL;
f4a8c29f 159
7b0bfbb2 160 return info->CreateObject();
f4a8c29f
GL
161}
162
856d2e52 163void wxLibrary::PrepareClasses(wxClassInfo *first)
f4a8c29f 164{
7b0bfbb2
VZ
165 // Index all class infos by their class name
166 wxClassInfo *info = first;
167 while (info)
168 {
169 if (info->m_className)
170 classTable.Put(info->m_className, (wxObject *)info);
6057972b 171 info = (wxClassInfo *)info->GetNext();
7b0bfbb2
VZ
172 }
173
174 // Set base pointers for each wxClassInfo
175 info = first;
176 while (info)
177 {
178 if (info->GetBaseClassName1())
179 info->m_baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
180 if (info->GetBaseClassName2())
181 info->m_baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
182 info = info->m_next;
183 }
7a4b9130
GL
184}
185
186void *wxLibrary::GetSymbol(const wxString& symbname)
187{
a585ca5c
KB
188 return wxDllLoader::GetSymbol(m_handle, symbname);
189}
7b0bfbb2 190
a585ca5c
KB
191// ---------------------------------------------------------------------------
192// wxDllLoader
193// ---------------------------------------------------------------------------
7b0bfbb2 194
f6bcfd97
BP
195/* static */
196wxString wxDllLoader::GetDllExt()
197{
198 wxString ext;
199
200#if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
201 ext = _T(".dll");
202#elif defined(__UNIX__)
203# if defined(__HPUX__)
204 ext = _T(".sl");
205# else //__HPUX__
206 ext = _T(".so");
207# endif //__HPUX__
208#endif
209
210 return ext;
211}
212
0868079c
KB
213/* static */
214wxDllType
215wxDllLoader::GetProgramHandle(void)
216{
1a787c5d 217#if defined( HAVE_DLOPEN ) && !defined(__EMX__)
7742efff 218 // optain handle for main program
d236a959 219 return dlopen(NULL, RTLD_NOW/*RTLD_LAZY*/);
7742efff
KB
220#elif defined (HAVE_SHL_LOAD)
221 // shl_findsymbol with NULL handle looks up in main program
d236a959 222 return 0;
0868079c 223#else
58c837a4 224 wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
7742efff 225 return 0;
7cc98b3e 226#endif
0868079c
KB
227}
228
a585ca5c
KB
229/* static */
230wxDllType
7cc98b3e 231wxDllLoader::LoadLibrary(const wxString & libname, bool *success)
a585ca5c 232{
7cc98b3e 233 wxDllType handle;
7b0bfbb2 234
03e11df5 235#if defined(__WXMAC__) && !defined(__UNIX__)
7cc98b3e 236 FSSpec myFSSpec ;
f6bcfd97
BP
237 Ptr myMainAddr ;
238 Str255 myErrName ;
7cc98b3e 239
763ca781 240 wxMacFilename2FSSpec( libname , &myFSSpec ) ;
7cc98b3e
VZ
241 if (GetDiskFragment( &myFSSpec , 0 , kCFragGoesToEOF , "\p" , kPrivateCFragCopy , &handle , &myMainAddr ,
242 myErrName ) != noErr )
243 {
244 p2cstr( myErrName ) ;
763ca781
SC
245 wxLogSysError( _("Failed to load shared library '%s' Error '%s'") , libname.c_str() , (char*)myErrName ) ;
246 handle = NULL ;
7cc98b3e 247 }
1a787c5d 248#elif defined(__WXPM__) || defined(__EMX__)
f6bcfd97 249 char zError[256] = "";
c2ff79b1 250 wxDllOpen(zError, libname, handle);
a585ca5c 251#else // !Mac
4c27c3c6 252 handle = wxDllOpen(libname);
a585ca5c
KB
253#endif // OS
254
7cc98b3e
VZ
255 if ( !handle )
256 {
f6bcfd97
BP
257 wxString msg(_("Failed to load shared library '%s'"));
258
259#ifdef HAVE_DLERROR
260 const char *errmsg = dlerror();
261 if ( errmsg )
262 {
263 // the error string format is "libname: ...", but we already have
264 // libname, so cut it off
265 const char *p = strchr(errmsg, ':');
266 if ( p )
267 {
268 if ( *++p == ' ' )
269 p++;
270 }
271 else
272 {
273 p = errmsg;
274 }
275
276 msg += _T(" (%s)");
277 wxLogError(msg, libname.c_str(), p);
278 }
279 else
280#endif // HAVE_DLERROR
281 {
282 wxLogSysError(msg, libname.c_str());
283 }
7cc98b3e
VZ
284 }
285
286 if ( success )
287 {
288 *success = handle != 0;
289 }
290
291 return handle;
a585ca5c
KB
292}
293
752c7d6b
KB
294
295/* static */
296void
297wxDllLoader::UnloadLibrary(wxDllType handle)
298{
299 wxDllClose(handle);
300}
301
a585ca5c
KB
302/* static */
303void *
304wxDllLoader::GetSymbol(wxDllType dllHandle, const wxString &name)
305{
7cc98b3e 306 void *symbol = NULL; // return value
a585ca5c 307
03e11df5 308#if defined(__WXMAC__) && !defined(__UNIX__)
7cc98b3e
VZ
309 Ptr symAddress ;
310 CFragSymbolClass symClass ;
f6bcfd97 311 Str255 symName ;
7cc98b3e 312
03e11df5
GD
313#if TARGET_CARBON
314 c2pstrcpy( (StringPtr) symName , name ) ;
315#else
316 strcpy( (char *) symName , name ) ;
317 c2pstr( (char *) symName ) ;
318#endif
7cc98b3e
VZ
319
320 if ( FindSymbol( dllHandle , symName , &symAddress , &symClass ) == noErr )
321 symbol = (void *)symAddress ;
1a787c5d 322#elif defined( __WXPM__ ) || defined(__EMX__)
c2ff79b1 323 wxDllGetSymbol(dllHandle, symbol);
7b0bfbb2 324#else
f6bcfd97 325 // mb_str() is necessary in Unicode build
4c27c3c6 326 symbol = wxDllGetSymbol(dllHandle, name.mb_str());
123a7fdd 327#endif
7b0bfbb2
VZ
328
329 if ( !symbol )
330 {
7cc98b3e
VZ
331 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
332 name.c_str());
7b0bfbb2 333 }
7b0bfbb2 334 return symbol;
7a4b9130
GL
335}
336
337// ---------------------------------------------------------------------------
338// wxLibraries (only one instance should normally exist)
339// ---------------------------------------------------------------------------
340
65fd5cb0 341wxLibraries::wxLibraries():m_loaded(wxKEY_STRING)
7a4b9130
GL
342{
343}
344
345wxLibraries::~wxLibraries()
346{
7b0bfbb2 347 wxNode *node = m_loaded.First();
7a4b9130 348
7b0bfbb2
VZ
349 while (node) {
350 wxLibrary *lib = (wxLibrary *)node->Data();
351 delete lib;
7a4b9130 352
7b0bfbb2
VZ
353 node = node->Next();
354 }
7a4b9130
GL
355}
356
357wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
358{
7b0bfbb2
VZ
359 wxNode *node;
360 wxLibrary *lib;
361 wxClassInfo *old_sm_first;
7a4b9130 362
c2ff79b1
DW
363#if defined(__VISAGECPP__)
364 node = m_loaded.Find(name.GetData());
365 if (node != NULL)
366 return ((wxLibrary *)node->Data());
367#else // !OS/2
33ac7e6f 368 if ( (node = m_loaded.Find(name.GetData())) != NULL)
7b0bfbb2 369 return ((wxLibrary *)node->Data());
c2ff79b1 370#endif
7b0bfbb2
VZ
371 // If DLL shares data, this is necessary.
372 old_sm_first = wxClassInfo::sm_first;
373 wxClassInfo::sm_first = NULL;
374
7cc98b3e 375 wxString libname = ConstructLibraryName(name);
856d2e52 376
a585ca5c
KB
377/*
378 Unix automatically builds that library name, at least for dlopen()
379*/
380#if 0
9e4b2f1c 381#if defined(__UNIX__)
8a0d4cf6
VZ
382 // found the first file in LD_LIBRARY_PATH with this name
383 wxString libPath("/lib:/usr/lib"); // system path first
384 const char *envLibPath = getenv("LD_LIBRARY_PATH");
385 if ( envLibPath )
58c837a4 386 libPath << wxT(':') << envLibPath;
223d09f6 387 wxStringTokenizer tokenizer(libPath, wxT(':'));
8a0d4cf6
VZ
388 while ( tokenizer.HasMoreToken() )
389 {
390 wxString fullname(tokenizer.NextToken());
391
58c837a4 392 fullname << wxT('/') << libname;
8a0d4cf6
VZ
393 if ( wxFileExists(fullname) )
394 {
7cc98b3e 395 libname = fullname;
8a0d4cf6
VZ
396
397 // found the library
398 break;
399 }
400 }
401 //else: not found in the path, leave the name as is (secutiry risk?)
402
7b0bfbb2 403#endif // __UNIX__
a585ca5c 404#endif
7a4b9130 405
4dc2c3bb 406 bool success = FALSE;
7cc98b3e 407 wxDllType handle = wxDllLoader::LoadLibrary(libname, &success);
a585ca5c 408 if(success)
7b0bfbb2 409 {
a585ca5c
KB
410 lib = new wxLibrary(handle);
411 wxClassInfo::sm_first = old_sm_first;
412 m_loaded.Append(name.GetData(), lib);
7b0bfbb2 413 }
a585ca5c
KB
414 else
415 lib = NULL;
7b0bfbb2 416 return lib;
7a4b9130
GL
417}
418
419wxObject *wxLibraries::CreateObject(const wxString& path)
420{
7b0bfbb2
VZ
421 wxNode *node = m_loaded.First();
422 wxObject *obj;
7a4b9130 423
7b0bfbb2
VZ
424 while (node) {
425 obj = ((wxLibrary *)node->Data())->CreateObject(path);
426 if (obj)
427 return obj;
7a4b9130 428
7b0bfbb2
VZ
429 node = node->Next();
430 }
431 return NULL;
7a4b9130 432}
8a0d4cf6
VZ
433
434#endif // wxUSE_DYNLIB_CLASS