]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/dynlib.cpp
Implemented the various printf() functions under
[wxWidgets.git] / src / common / dynlib.cpp
... / ...
CommitLineData
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
30#if wxUSE_DYNLIB_CLASS && !wxUSE_DYNAMIC_LOADER
31
32#if defined(__WINDOWS__)
33 #include "wx/msw/private.h"
34#endif
35
36#include "wx/dynlib.h"
37#include "wx/filefn.h"
38#include "wx/intl.h"
39#include "wx/log.h"
40
41#if defined(__WXMAC__)
42 #include "wx/mac/private.h"
43#endif
44
45// ----------------------------------------------------------------------------
46// conditional compilation
47// ----------------------------------------------------------------------------
48
49#if defined(__WXPM__) || defined(__EMX__)
50# define INCL_DOS
51# include <os2.h>
52# define wxDllOpen(error, lib, handle) DosLoadModule(error, sizeof(error), lib, &handle)
53# define wxDllGetSymbol(handle, modaddr) DosQueryProcAddr(handle, 1L, NULL, (PFN*)modaddr)
54# define wxDllClose(handle) DosFreeModule(handle)
55#elif defined(HAVE_DLOPEN)
56 // note about dlopen() flags: we use RTLD_NOW to have more Windows-like
57 // behaviour (Win won't let you load a library with missing symbols) and
58 // RTLD_GLOBAL because it is needed sometimes and probably doesn't hurt
59 // otherwise. On True64-Unix RTLD_GLOBAL is not allowed and on VMS the
60 // second argument on dlopen is ignored.
61#ifdef __VMS
62# define wxDllOpen(lib) dlopen(lib.fn_str(), 0 )
63#elif defined( __osf__ )
64# define wxDllOpen(lib) dlopen(lib.fn_str(), RTLD_LAZY )
65#else
66# define wxDllOpen(lib) dlopen(lib.fn_str(), RTLD_LAZY | RTLD_GLOBAL)
67#endif
68#define wxDllGetSymbol(handle, name) dlsym(handle, name)
69# define wxDllClose dlclose
70#elif defined(HAVE_SHL_LOAD)
71# define wxDllOpen(lib) shl_load(lib.fn_str(), BIND_DEFERRED, 0)
72# define wxDllClose shl_unload
73
74static inline void *wxDllGetSymbol(shl_t handle, const wxString& name)
75{
76 void *sym;
77 if ( shl_findsym(&handle, name.mb_str(), TYPE_UNDEFINED, &sym) == 0 )
78 return sym;
79 else
80 return 0;
81}
82
83#elif defined(__DARWIN__)
84/* Porting notes:
85 * The dlopen port is a port from dl_next.xs by Anno Siegel.
86 * dl_next.xs is itself a port from dl_dlopen.xs by Paul Marquess.
87 * The method used here is just to supply the sun style dlopen etc.
88 * functions in terms of Darwin NS*.
89 */
90void *dlopen(const char *path, int mode /* mode is ignored */);
91void *dlsym(void *handle, const char *symbol);
92int dlclose(void *handle);
93const char *dlerror(void);
94
95# define wxDllOpen(lib) dlopen(lib.fn_str(), 0)
96# define wxDllGetSymbol(handle, name) dlsym(handle, name)
97# define wxDllClose dlclose
98#elif defined(__WINDOWS__)
99 // using LoadLibraryEx under Win32 to avoid name clash with LoadLibrary
100# ifdef __WIN32__
101#ifdef _UNICODE
102# define wxDllOpen(lib) ::LoadLibraryExW(lib, 0, 0)
103#else
104# define wxDllOpen(lib) ::LoadLibraryExA(lib, 0, 0)
105#endif
106# else // Win16
107# define wxDllOpen(lib) ::LoadLibrary(lib)
108# endif // Win32/16
109# define wxDllGetSymbol(handle, name) ::GetProcAddress(handle, name)
110# define wxDllClose ::FreeLibrary
111#elif defined(__WXMAC__)
112# define wxDllClose(handle) CloseConnection(&((CFragConnectionID)handle))
113#else
114# error "Don't know how to load shared libraries on this platform."
115#endif // OS
116
117// ---------------------------------------------------------------------------
118// Global variables
119// ---------------------------------------------------------------------------
120
121wxLibraries wxTheLibraries;
122
123// ============================================================================
124// implementation
125// ============================================================================
126
127// construct the full name from the base shared object name: adds a .dll
128// suffix under Windows or .so under Unix
129static wxString ConstructLibraryName(const wxString& basename)
130{
131 wxString fullname;
132 fullname << basename << wxDllLoader::GetDllExt();
133
134 return fullname;
135}
136
137// ---------------------------------------------------------------------------
138// wxLibrary (one instance per dynamic library)
139// ---------------------------------------------------------------------------
140
141wxLibrary::wxLibrary(wxDllType handle)
142{
143 typedef wxClassInfo *(*t_get_first)(void);
144 t_get_first get_first;
145
146 m_handle = handle;
147
148 // Some system may use a local heap for library.
149 get_first = (t_get_first)GetSymbol("wxGetClassFirst");
150 // It is a wxWindows DLL.
151 if (get_first)
152 PrepareClasses(get_first());
153}
154
155wxLibrary::~wxLibrary()
156{
157 if ( m_handle )
158 {
159 wxDllClose(m_handle);
160 }
161}
162
163wxObject *wxLibrary::CreateObject(const wxString& name)
164{
165 wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
166
167 if (!info)
168 return NULL;
169
170 return info->CreateObject();
171}
172
173void wxLibrary::PrepareClasses(wxClassInfo *first)
174{
175 // Index all class infos by their class name
176 wxClassInfo *info = first;
177 while (info)
178 {
179 if (info->m_className)
180 classTable.Put(info->m_className, (wxObject *)info);
181 info = info->m_next;
182 }
183
184 // Set base pointers for each wxClassInfo
185 info = first;
186 while (info)
187 {
188 if (info->GetBaseClassName1())
189 info->m_baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
190 if (info->GetBaseClassName2())
191 info->m_baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
192 info = info->m_next;
193 }
194}
195
196void *wxLibrary::GetSymbol(const wxString& symbname)
197{
198 return wxDllLoader::GetSymbol(m_handle, symbname);
199}
200
201// ---------------------------------------------------------------------------
202// wxDllLoader
203// ---------------------------------------------------------------------------
204
205
206#if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
207const wxString wxDllLoader::ms_dllext( _T(".dll") );
208#elif defined(__UNIX__)
209#if defined(__HPUX__)
210const wxString wxDllLoader::ms_dllext( _T(".sl") );
211#else
212const wxString wxDllLoader::ms_dllext( _T(".so") );
213#endif
214#elif defined(__WXMAC__)
215const wxString wxDllLoader::ms_dllext( _T("") );
216#endif
217
218/* static */
219wxDllType wxDllLoader::GetProgramHandle()
220{
221#if defined( HAVE_DLOPEN ) && !defined(__EMX__)
222 // optain handle for main program
223 return dlopen(NULL, RTLD_NOW/*RTLD_LAZY*/);
224#elif defined (HAVE_SHL_LOAD)
225 // shl_findsymbol with NULL handle looks up in main program
226 return 0;
227#else
228 wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
229 return 0;
230#endif
231}
232
233/* static */
234wxDllType wxDllLoader::LoadLibrary(const wxString & libname, bool *success)
235{
236 wxDllType handle;
237 bool failed = FALSE;
238
239#if defined(__WXMAC__) && !defined(__UNIX__)
240 FSSpec myFSSpec;
241 Ptr myMainAddr;
242 Str255 myErrName;
243
244 wxMacFilename2FSSpec( libname , &myFSSpec );
245
246 if( GetDiskFragment( &myFSSpec,
247 0,
248 kCFragGoesToEOF,
249 "\p",
250 kPrivateCFragCopy,
251 &((CFragConnectionID)handle),
252 &myMainAddr,
253 myErrName ) != noErr )
254 {
255 p2cstr( myErrName );
256 wxLogSysError( _("Failed to load shared library '%s' Error '%s'"),
257 libname.c_str(),
258 (char*)myErrName );
259 handle = 0;
260 failed = TRUE;
261 }
262
263#elif defined(__WXPM__) || defined(__EMX__)
264 char zError[256] = "";
265 wxDllOpen(zError, libname, handle);
266
267#else
268 handle = wxDllOpen(libname);
269
270#endif
271
272 if ( !handle )
273 {
274 wxString msg(_("Failed to load shared library '%s'"));
275
276#ifdef HAVE_DLERROR
277 const wxChar *err = dlerror();
278 if( err )
279 {
280 failed = TRUE;
281 wxLogError( msg, err );
282 }
283#else
284 failed = TRUE;
285 wxLogSysError( msg, libname.c_str() );
286#endif
287 }
288
289 if ( success )
290 *success = !failed;
291
292 return handle;
293}
294
295
296/* static */
297void wxDllLoader::UnloadLibrary(wxDllType handle)
298{
299 wxDllClose(handle);
300}
301
302/* static */
303void *wxDllLoader::GetSymbol(wxDllType dllHandle, const wxString &name, bool *success)
304{
305 bool failed = FALSE;
306 void *symbol = 0;
307
308#if defined(__WXMAC__) && !defined(__UNIX__)
309 Ptr symAddress;
310 CFragSymbolClass symClass;
311 Str255 symName;
312
313#if TARGET_CARBON
314 c2pstrcpy( (StringPtr) symName, name );
315#else
316 strcpy( (char *) symName, name );
317 c2pstr( (char *) symName );
318#endif
319 if( FindSymbol( ((CFragConnectionID)dllHandle), symName, &symAddress, &symClass ) == noErr )
320 symbol = (void *)symAddress;
321
322#elif defined(__WXPM__) || defined(__EMX__)
323 wxDllGetSymbol(dllHandle, symbol);
324
325#else // Windows or Unix
326
327 // mb_str() is necessary in Unicode build
328 //
329 // "void *" cast is needed by gcc 3.1 + w32api 1.4, don't ask me why
330 symbol = (void *)wxDllGetSymbol(dllHandle, name.mb_str());
331
332#endif // OS
333
334 if ( !symbol )
335 {
336 wxString msg(_("wxDllLoader failed to GetSymbol '%s'"));
337
338#ifdef HAVE_DLERROR
339 const wxChar *err = dlerror();
340 if( err )
341 {
342 failed = TRUE;
343 wxLogError( msg, err );
344 }
345#else
346 failed = TRUE;
347 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
348 name.c_str());
349#endif
350 }
351
352 if( success )
353 *success = !failed;
354
355 return symbol;
356}
357
358// ---------------------------------------------------------------------------
359// wxLibraries (only one instance should normally exist)
360// ---------------------------------------------------------------------------
361
362wxLibraries::wxLibraries():m_loaded(wxKEY_STRING)
363{
364}
365
366wxLibraries::~wxLibraries()
367{
368 wxNode *node = m_loaded.First();
369
370 while (node) {
371 wxLibrary *lib = (wxLibrary *)node->Data();
372 delete lib;
373
374 node = node->Next();
375 }
376}
377
378wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
379{
380 wxLibrary *lib;
381 wxClassInfo *old_sm_first;
382 wxNode *node = m_loaded.Find(name.GetData());
383
384 if (node != NULL)
385 return ((wxLibrary *)node->Data());
386
387 // If DLL shares data, this is necessary.
388 old_sm_first = wxClassInfo::sm_first;
389 wxClassInfo::sm_first = NULL;
390
391 wxString libname = ConstructLibraryName(name);
392
393 bool success = FALSE;
394 wxDllType handle = wxDllLoader::LoadLibrary(libname, &success);
395 if(success)
396 {
397 lib = new wxLibrary(handle);
398 wxClassInfo::sm_first = old_sm_first;
399
400 m_loaded.Append(name.GetData(), lib);
401 }
402 else
403 lib = NULL;
404 return lib;
405}
406
407wxObject *wxLibraries::CreateObject(const wxString& path)
408{
409 wxNode *node = m_loaded.First();
410 wxObject *obj;
411
412 while (node) {
413 obj = ((wxLibrary *)node->Data())->CreateObject(path);
414 if (obj)
415 return obj;
416
417 node = node->Next();
418 }
419 return NULL;
420}
421
422#endif // wxUSE_DYNLIB_CLASS && !wxUSE_DYNAMIC_LOADER
423
424#if defined(__DARWIN__) && (wxUSE_DYNLIB_CLASS || wxUSE_DYNAMIC_LOADER)
425// ---------------------------------------------------------------------------
426// For Darwin/Mac OS X
427// supply the sun style dlopen functions in terms of Darwin NS*
428// ---------------------------------------------------------------------------
429
430#include <stdio.h>
431#include <mach-o/dyld.h>
432
433static char dl_last_error[1024];
434
435static
436void TranslateError(const char *path, int number)
437{
438 unsigned int index;
439 static char *OFIErrorStrings[] =
440 {
441 "%s(%d): Object Image Load Failure\n",
442 "%s(%d): Object Image Load Success\n",
443 "%s(%d): Not an recognisable object file\n",
444 "%s(%d): No valid architecture\n",
445 "%s(%d): Object image has an invalid format\n",
446 "%s(%d): Invalid access (permissions?)\n",
447 "%s(%d): Unknown error code from NSCreateObjectFileImageFromFile\n",
448 };
449#define NUM_OFI_ERRORS (sizeof(OFIErrorStrings) / sizeof(OFIErrorStrings[0]))
450
451 index = number;
452 if (index > NUM_OFI_ERRORS - 1) {
453 index = NUM_OFI_ERRORS - 1;
454 }
455 sprintf(dl_last_error, OFIErrorStrings[index], path, number);
456}
457
458const char *dlerror()
459{
460 return dl_last_error;
461}
462
463void *dlopen(const char *path, int WXUNUSED(mode) /* mode is ignored */)
464{
465 int dyld_result;
466 NSObjectFileImage ofile;
467 NSModule handle = NULL;
468
469 dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
470 if (dyld_result != NSObjectFileImageSuccess)
471 {
472 TranslateError(path, dyld_result);
473 }
474 else
475 {
476 // NSLinkModule will cause the run to abort on any link error's
477 // not very friendly but the error recovery functionality is limited.
478 handle = NSLinkModule(ofile, path, NSLINKMODULE_OPTION_BINDNOW);
479 }
480
481 return handle;
482}
483
484int dlclose(void *handle)
485{
486 NSUnLinkModule( handle, NSUNLINKMODULE_OPTION_NONE);
487 return 0;
488}
489
490void *dlsym(void *WXUNUSED(handle), const char *symbol)
491{
492 void *addr;
493
494 if (NSIsSymbolNameDefined(symbol)) {
495 addr = NSAddressOfSymbol(NSLookupAndBindSymbol(symbol));
496 }
497 else {
498 addr = NULL;
499 }
500 return addr;
501}
502
503#endif // defined(__DARWIN__) && (wxUSE_DYNLIB_CLASS || wxUSE_DYNAMIC_LOADER)