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