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