]> git.saurik.com Git - wxWidgets.git/blob - src/common/dynlib.cpp
assert in GetNextItem() fixed (?)
[wxWidgets.git] / src / common / dynlib.cpp
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 #if defined(__WINDOWS__)
26 #include "wx/msw/private.h"
27 #endif
28
29 #ifdef __BORLANDC__
30 #pragma hdrstop
31 #endif
32 #if wxUSE_DYNLIB_CLASS
33
34 #include "wx/dynlib.h"
35 #include "wx/filefn.h"
36 #include "wx/intl.h"
37 #include "wx/log.h"
38 #include "wx/tokenzr.h"
39
40 // ----------------------------------------------------------------------------
41 // conditional compilation
42 // ----------------------------------------------------------------------------
43
44 #if defined(HAVE_DLOPEN)
45 # define wxDllOpen(lib) dlopen(lib.fn_str(), RTLD_NOW/*RTLD_LAZY*/)
46 # define wxDllGetSymbol(handle, name) dlsym(handle, name.mb_str())
47 # define wxDllClose dlclose
48 #elif defined(HAVE_SHL_LOAD)
49 # define wxDllOpen(lib) shl_load(lib.fn_str(), BIND_DEFERRED, 0)
50 # define wxDllClose shl_unload
51
52 static inline void *wxDllGetSymbol(shl_t handle, const wxString& name)
53 {
54 void *sym;
55 if ( shl_findsym(&handle, name.mb_str(), TYPE_UNDEFINED, &sym) == 0 )
56 return sym;
57 else
58 return (void *)0;
59 }
60 #elif defined(__WINDOWS__)
61 // using LoadLibraryEx under Win32 to avoid name clash with LoadLibrary
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
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)
77 #else
78 # error "Don't know how to load shared libraries on this platform."
79 #endif // OS
80
81 // ---------------------------------------------------------------------------
82 // Global variables
83 // ---------------------------------------------------------------------------
84
85 wxLibraries wxTheLibraries;
86
87 // ----------------------------------------------------------------------------
88 // private functions
89 // ----------------------------------------------------------------------------
90
91 // construct the full name from the base shared object name: adds a .dll
92 // suffix under Windows or .so under Unix
93 static wxString ConstructLibraryName(const wxString& basename)
94 {
95 wxString fullname(basename);
96
97 #if defined(__UNIX__)
98 # if defined(__HPUX__)
99 fullname << ".sl";
100 # else //__HPUX__
101 fullname << ".so";
102 # endif //__HPUX__
103 #elif defined(__WINDOWS__) || defined(__OS2__)
104 fullname << ".dll";
105 #endif
106
107 return fullname;
108 }
109
110 // ============================================================================
111 // implementation
112 // ============================================================================
113
114
115 // ---------------------------------------------------------------------------
116 // wxLibrary (one instance per dynamic library)
117 // ---------------------------------------------------------------------------
118
119 wxLibrary::wxLibrary(wxDllType handle)
120 {
121 typedef wxClassInfo *(*t_get_first)(void);
122 t_get_first get_first;
123
124 m_handle = handle;
125
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());
131 }
132
133 wxLibrary::~wxLibrary()
134 {
135 if ( m_handle )
136 {
137 wxDllClose(m_handle);
138 }
139 }
140
141 wxObject *wxLibrary::CreateObject(const wxString& name)
142 {
143 wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
144
145 if (!info)
146 return NULL;
147
148 return info->CreateObject();
149 }
150
151 void wxLibrary::PrepareClasses(wxClassInfo *first)
152 {
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 }
172 }
173
174 void *wxLibrary::GetSymbol(const wxString& symbname)
175 {
176 return wxDllLoader::GetSymbol(m_handle, symbname);
177 }
178
179 // ---------------------------------------------------------------------------
180 // wxDllLoader
181 // ---------------------------------------------------------------------------
182
183 /* static */
184 wxDllType
185 wxDllLoader::GetProgramHandle(void)
186 {
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;
193 #else
194 wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
195 return 0;
196 #endif
197 }
198
199 /* static */
200 wxDllType
201 wxDllLoader::LoadLibrary(const wxString & libname, bool *success)
202 {
203 wxDllType handle;
204
205 #if defined(__WXMAC__)
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 }
218 #elif defined(__OS2__)
219 char zError[256] = "";
220 wxDllOpen(zError, libname, handle);
221 #else // !Mac
222 handle = wxDllOpen(libname);
223 #endif // OS
224
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;
236 }
237
238
239 /* static */
240 void
241 wxDllLoader::UnloadLibrary(wxDllType handle)
242 {
243 wxDllClose(handle);
244 }
245
246 /* static */
247 void *
248 wxDllLoader::GetSymbol(wxDllType dllHandle, const wxString &name)
249 {
250 void *symbol = NULL; // return value
251
252 #if defined( __WXMAC__ )
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 ;
262 #elif defined( __OS2__ )
263 wxDllGetSymbol(dllHandle, symbol);
264 #else
265 symbol = wxDllGetSymbol(dllHandle, name);
266 #endif
267
268 if ( !symbol )
269 {
270 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
271 name.c_str());
272 }
273 return symbol;
274 }
275
276 // ---------------------------------------------------------------------------
277 // wxLibraries (only one instance should normally exist)
278 // ---------------------------------------------------------------------------
279
280 wxLibraries::wxLibraries():m_loaded(wxKEY_STRING)
281 {
282 }
283
284 wxLibraries::~wxLibraries()
285 {
286 wxNode *node = m_loaded.First();
287
288 while (node) {
289 wxLibrary *lib = (wxLibrary *)node->Data();
290 delete lib;
291
292 node = node->Next();
293 }
294 }
295
296 wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
297 {
298 wxNode *node;
299 wxLibrary *lib;
300 wxClassInfo *old_sm_first;
301
302 #if defined(__VISAGECPP__)
303 node = m_loaded.Find(name.GetData());
304 if (node != NULL)
305 return ((wxLibrary *)node->Data());
306 #else // !OS/2
307 if ( (node = m_loaded.Find(name.GetData())) )
308 return ((wxLibrary *)node->Data());
309 #endif
310 // If DLL shares data, this is necessary.
311 old_sm_first = wxClassInfo::sm_first;
312 wxClassInfo::sm_first = NULL;
313
314 wxString libname = ConstructLibraryName(name);
315
316 /*
317 Unix automatically builds that library name, at least for dlopen()
318 */
319 #if 0
320 #if defined(__UNIX__)
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 )
325 libPath << wxT(':') << envLibPath;
326 wxStringTokenizer tokenizer(libPath, wxT(':'));
327 while ( tokenizer.HasMoreToken() )
328 {
329 wxString fullname(tokenizer.NextToken());
330
331 fullname << wxT('/') << libname;
332 if ( wxFileExists(fullname) )
333 {
334 libname = fullname;
335
336 // found the library
337 break;
338 }
339 }
340 //else: not found in the path, leave the name as is (secutiry risk?)
341
342 #endif // __UNIX__
343 #endif
344
345 bool success = FALSE;
346 wxDllType handle = wxDllLoader::LoadLibrary(libname, &success);
347 if(success)
348 {
349 lib = new wxLibrary(handle);
350 wxClassInfo::sm_first = old_sm_first;
351 m_loaded.Append(name.GetData(), lib);
352 }
353 else
354 lib = NULL;
355 return lib;
356 }
357
358 wxObject *wxLibraries::CreateObject(const wxString& path)
359 {
360 wxNode *node = m_loaded.First();
361 wxObject *obj;
362
363 while (node) {
364 obj = ((wxLibrary *)node->Data())->CreateObject(path);
365 if (obj)
366 return obj;
367
368 node = node->Next();
369 }
370 return NULL;
371 }
372
373 #endif // wxUSE_DYNLIB_CLASS