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