]> git.saurik.com Git - wxWidgets.git/blame - src/common/dynlib.cpp
Minor mods
[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
7b0bfbb2 101#else
a585ca5c 102# error "Don't know how to load shared libraries on this platform."
7b0bfbb2 103#endif // OS
7a4b9130
GL
104
105// ---------------------------------------------------------------------------
7b0bfbb2 106// Global variables
7a4b9130
GL
107// ---------------------------------------------------------------------------
108
7b0bfbb2 109wxLibraries wxTheLibraries;
7a4b9130 110
f6bcfd97
BP
111// ============================================================================
112// implementation
113// ============================================================================
123a7fdd 114
7b0bfbb2
VZ
115// construct the full name from the base shared object name: adds a .dll
116// suffix under Windows or .so under Unix
117static wxString ConstructLibraryName(const wxString& basename)
118{
f6bcfd97
BP
119 wxString fullname;
120 fullname << basename << wxDllLoader::GetDllExt();
27529614 121
7b0bfbb2
VZ
122 return fullname;
123}
7a4b9130 124
7a4b9130 125// ---------------------------------------------------------------------------
7b0bfbb2 126// wxLibrary (one instance per dynamic library)
7a4b9130
GL
127// ---------------------------------------------------------------------------
128
7b0bfbb2 129wxLibrary::wxLibrary(wxDllType handle)
7a4b9130 130{
7b0bfbb2
VZ
131 typedef wxClassInfo *(*t_get_first)(void);
132 t_get_first get_first;
7a4b9130 133
7b0bfbb2 134 m_handle = handle;
7a4b9130 135
7b0bfbb2
VZ
136 // Some system may use a local heap for library.
137 get_first = (t_get_first)GetSymbol("wxGetClassFirst");
138 // It is a wxWindows DLL.
139 if (get_first)
140 PrepareClasses(get_first());
7a4b9130
GL
141}
142
143wxLibrary::~wxLibrary()
144{
7b0bfbb2
VZ
145 if ( m_handle )
146 {
147 wxDllClose(m_handle);
148 }
7a4b9130
GL
149}
150
151wxObject *wxLibrary::CreateObject(const wxString& name)
152{
7b0bfbb2 153 wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
f4a8c29f 154
7b0bfbb2
VZ
155 if (!info)
156 return NULL;
f4a8c29f 157
7b0bfbb2 158 return info->CreateObject();
f4a8c29f
GL
159}
160
856d2e52 161void wxLibrary::PrepareClasses(wxClassInfo *first)
f4a8c29f 162{
7b0bfbb2
VZ
163 // Index all class infos by their class name
164 wxClassInfo *info = first;
165 while (info)
166 {
167 if (info->m_className)
168 classTable.Put(info->m_className, (wxObject *)info);
6057972b 169 info = (wxClassInfo *)info->GetNext();
7b0bfbb2
VZ
170 }
171
172 // Set base pointers for each wxClassInfo
173 info = first;
174 while (info)
175 {
176 if (info->GetBaseClassName1())
177 info->m_baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
178 if (info->GetBaseClassName2())
179 info->m_baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
180 info = info->m_next;
181 }
7a4b9130
GL
182}
183
184void *wxLibrary::GetSymbol(const wxString& symbname)
185{
a585ca5c
KB
186 return wxDllLoader::GetSymbol(m_handle, symbname);
187}
7b0bfbb2 188
a585ca5c
KB
189// ---------------------------------------------------------------------------
190// wxDllLoader
191// ---------------------------------------------------------------------------
7b0bfbb2 192
f6bcfd97
BP
193/* static */
194wxString wxDllLoader::GetDllExt()
195{
196 wxString ext;
197
198#if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
199 ext = _T(".dll");
200#elif defined(__UNIX__)
201# if defined(__HPUX__)
202 ext = _T(".sl");
203# else //__HPUX__
204 ext = _T(".so");
205# endif //__HPUX__
206#endif
207
208 return ext;
209}
210
0868079c
KB
211/* static */
212wxDllType
213wxDllLoader::GetProgramHandle(void)
214{
1a787c5d 215#if defined( HAVE_DLOPEN ) && !defined(__EMX__)
7742efff 216 // optain handle for main program
d236a959 217 return dlopen(NULL, RTLD_NOW/*RTLD_LAZY*/);
7742efff
KB
218#elif defined (HAVE_SHL_LOAD)
219 // shl_findsymbol with NULL handle looks up in main program
d236a959 220 return 0;
0868079c 221#else
58c837a4 222 wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
7742efff 223 return 0;
7cc98b3e 224#endif
0868079c
KB
225}
226
a585ca5c
KB
227/* static */
228wxDllType
7cc98b3e 229wxDllLoader::LoadLibrary(const wxString & libname, bool *success)
a585ca5c 230{
7cc98b3e 231 wxDllType handle;
7b0bfbb2 232
03e11df5 233#if defined(__WXMAC__) && !defined(__UNIX__)
7cc98b3e 234 FSSpec myFSSpec ;
f6bcfd97
BP
235 Ptr myMainAddr ;
236 Str255 myErrName ;
7cc98b3e
VZ
237
238 wxMacPathToFSSpec( libname , &myFSSpec ) ;
239 if (GetDiskFragment( &myFSSpec , 0 , kCFragGoesToEOF , "\p" , kPrivateCFragCopy , &handle , &myMainAddr ,
240 myErrName ) != noErr )
241 {
242 p2cstr( myErrName ) ;
243 wxASSERT_MSG( 1 , (char*)myErrName ) ;
244 return NULL ;
245 }
1a787c5d 246#elif defined(__WXPM__) || defined(__EMX__)
f6bcfd97 247 char zError[256] = "";
c2ff79b1 248 wxDllOpen(zError, libname, handle);
a585ca5c 249#else // !Mac
4c27c3c6 250 handle = wxDllOpen(libname);
a585ca5c
KB
251#endif // OS
252
7cc98b3e
VZ
253 if ( !handle )
254 {
f6bcfd97
BP
255 wxString msg(_("Failed to load shared library '%s'"));
256
257#ifdef HAVE_DLERROR
258 const char *errmsg = dlerror();
259 if ( errmsg )
260 {
261 // the error string format is "libname: ...", but we already have
262 // libname, so cut it off
263 const char *p = strchr(errmsg, ':');
264 if ( p )
265 {
266 if ( *++p == ' ' )
267 p++;
268 }
269 else
270 {
271 p = errmsg;
272 }
273
274 msg += _T(" (%s)");
275 wxLogError(msg, libname.c_str(), p);
276 }
277 else
278#endif // HAVE_DLERROR
279 {
280 wxLogSysError(msg, libname.c_str());
281 }
7cc98b3e
VZ
282 }
283
284 if ( success )
285 {
286 *success = handle != 0;
287 }
288
289 return handle;
a585ca5c
KB
290}
291
752c7d6b
KB
292
293/* static */
294void
295wxDllLoader::UnloadLibrary(wxDllType handle)
296{
297 wxDllClose(handle);
298}
299
a585ca5c
KB
300/* static */
301void *
302wxDllLoader::GetSymbol(wxDllType dllHandle, const wxString &name)
303{
7cc98b3e 304 void *symbol = NULL; // return value
a585ca5c 305
03e11df5 306#if defined(__WXMAC__) && !defined(__UNIX__)
7cc98b3e
VZ
307 Ptr symAddress ;
308 CFragSymbolClass symClass ;
f6bcfd97 309 Str255 symName ;
7cc98b3e 310
03e11df5
GD
311#if TARGET_CARBON
312 c2pstrcpy( (StringPtr) symName , name ) ;
313#else
314 strcpy( (char *) symName , name ) ;
315 c2pstr( (char *) symName ) ;
316#endif
7cc98b3e
VZ
317
318 if ( FindSymbol( dllHandle , symName , &symAddress , &symClass ) == noErr )
319 symbol = (void *)symAddress ;
1a787c5d 320#elif defined( __WXPM__ ) || defined(__EMX__)
c2ff79b1 321 wxDllGetSymbol(dllHandle, symbol);
7b0bfbb2 322#else
f6bcfd97 323 // mb_str() is necessary in Unicode build
4c27c3c6 324 symbol = wxDllGetSymbol(dllHandle, name.mb_str());
123a7fdd 325#endif
7b0bfbb2
VZ
326
327 if ( !symbol )
328 {
7cc98b3e
VZ
329 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
330 name.c_str());
7b0bfbb2 331 }
7b0bfbb2 332 return symbol;
7a4b9130
GL
333}
334
335// ---------------------------------------------------------------------------
336// wxLibraries (only one instance should normally exist)
337// ---------------------------------------------------------------------------
338
65fd5cb0 339wxLibraries::wxLibraries():m_loaded(wxKEY_STRING)
7a4b9130
GL
340{
341}
342
343wxLibraries::~wxLibraries()
344{
7b0bfbb2 345 wxNode *node = m_loaded.First();
7a4b9130 346
7b0bfbb2
VZ
347 while (node) {
348 wxLibrary *lib = (wxLibrary *)node->Data();
349 delete lib;
7a4b9130 350
7b0bfbb2
VZ
351 node = node->Next();
352 }
7a4b9130
GL
353}
354
355wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
356{
7b0bfbb2
VZ
357 wxNode *node;
358 wxLibrary *lib;
359 wxClassInfo *old_sm_first;
7a4b9130 360
c2ff79b1
DW
361#if defined(__VISAGECPP__)
362 node = m_loaded.Find(name.GetData());
363 if (node != NULL)
364 return ((wxLibrary *)node->Data());
365#else // !OS/2
3897b707
GT
366 node = m_loaded.Find(name.GetData());
367 if ( node )
7b0bfbb2 368 return ((wxLibrary *)node->Data());
c2ff79b1 369#endif
7b0bfbb2
VZ
370 // If DLL shares data, this is necessary.
371 old_sm_first = wxClassInfo::sm_first;
372 wxClassInfo::sm_first = NULL;
373
7cc98b3e 374 wxString libname = ConstructLibraryName(name);
856d2e52 375
a585ca5c
KB
376/*
377 Unix automatically builds that library name, at least for dlopen()
378*/
379#if 0
9e4b2f1c 380#if defined(__UNIX__)
8a0d4cf6
VZ
381 // found the first file in LD_LIBRARY_PATH with this name
382 wxString libPath("/lib:/usr/lib"); // system path first
383 const char *envLibPath = getenv("LD_LIBRARY_PATH");
384 if ( envLibPath )
58c837a4 385 libPath << wxT(':') << envLibPath;
223d09f6 386 wxStringTokenizer tokenizer(libPath, wxT(':'));
8a0d4cf6
VZ
387 while ( tokenizer.HasMoreToken() )
388 {
389 wxString fullname(tokenizer.NextToken());
390
58c837a4 391 fullname << wxT('/') << libname;
8a0d4cf6
VZ
392 if ( wxFileExists(fullname) )
393 {
7cc98b3e 394 libname = fullname;
8a0d4cf6
VZ
395
396 // found the library
397 break;
398 }
399 }
400 //else: not found in the path, leave the name as is (secutiry risk?)
401
7b0bfbb2 402#endif // __UNIX__
a585ca5c 403#endif
7a4b9130 404
4dc2c3bb 405 bool success = FALSE;
7cc98b3e 406 wxDllType handle = wxDllLoader::LoadLibrary(libname, &success);
a585ca5c 407 if(success)
7b0bfbb2 408 {
a585ca5c
KB
409 lib = new wxLibrary(handle);
410 wxClassInfo::sm_first = old_sm_first;
411 m_loaded.Append(name.GetData(), lib);
7b0bfbb2 412 }
a585ca5c
KB
413 else
414 lib = NULL;
7b0bfbb2 415 return lib;
7a4b9130
GL
416}
417
418wxObject *wxLibraries::CreateObject(const wxString& path)
419{
7b0bfbb2
VZ
420 wxNode *node = m_loaded.First();
421 wxObject *obj;
7a4b9130 422
7b0bfbb2
VZ
423 while (node) {
424 obj = ((wxLibrary *)node->Data())->CreateObject(path);
425 if (obj)
426 return obj;
7a4b9130 427
7b0bfbb2
VZ
428 node = node->Next();
429 }
430 return NULL;
7a4b9130 431}
8a0d4cf6
VZ
432
433#endif // wxUSE_DYNLIB_CLASS