]> git.saurik.com Git - wxWidgets.git/blob - src/common/dynlib.cpp
support for incorrect entries in .mime.types added (world is not perfect, alas)
[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
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif //__BORLANDC__
29
30 #if wxUSE_DYNLIB_CLASS
31
32 #include "wx/dynlib.h"
33 #include "wx/filefn.h"
34 #include "wx/intl.h"
35 #include "wx/log.h"
36 #include "wx/tokenzr.h"
37
38 // ----------------------------------------------------------------------------
39 // conditional compilation
40 // ----------------------------------------------------------------------------
41
42 #if defined(HAVE_DLOPEN)
43 #define wxDllOpen(lib) dlopen(lib, RTLD_LAZY)
44 #define wxDllGetSymbol(handle, name) dlsym(handle, (char *)name)
45 #define wxDllClose dlclose
46 #elif defined(HAVE_SHL_LOAD)
47 #define wxDllOpen(lib) shl_load(lib, BIND_DEFERRED, 0)
48 #define wxDllClose shl_unload
49
50 static inline void *wxDllGetSymbol(shl_t handle, const char *name)
51 {
52 void *sym;
53 if ( shl_findsym(&handle, name, TYPE_UNDEFINED, &sym) == 0 )
54 return sym;
55 else
56 return (void *)0;
57 }
58 #elif defined(__WINDOWS__)
59 #define wxDllOpen(lib) ::LoadLibrary(lib)
60 #define wxDllGetSymbol(handle, name) ::GetProcAddress(handle, name)
61 #define wxDllClose ::FreeLibrary
62 #else
63 #error "Don't know how to load shared libraries on this platform."
64 #endif // OS
65
66 // ---------------------------------------------------------------------------
67 // Global variables
68 // ---------------------------------------------------------------------------
69
70 wxLibraries wxTheLibraries;
71
72 // ----------------------------------------------------------------------------
73 // private functions
74 // ----------------------------------------------------------------------------
75
76 // construct the full name from the base shared object name: adds a .dll
77 // suffix under Windows or .so under Unix
78 static wxString ConstructLibraryName(const wxString& basename)
79 {
80 wxString fullname(basename);
81
82 #if defined(__UNIX__)
83 #if defined(__HPUX__)
84 fullname << ".sl";
85 #else //__HPUX__
86 fullname << ".so";
87 #endif //__HPUX__
88 #elif defined(__WINDOWS__)
89 fullname << ".dll";
90 #endif
91
92 return fullname;
93 }
94
95 // ============================================================================
96 // implementation
97 // ============================================================================
98
99 // ---------------------------------------------------------------------------
100 // wxLibrary (one instance per dynamic library)
101 // ---------------------------------------------------------------------------
102
103 wxLibrary::wxLibrary(wxDllType handle)
104 {
105 typedef wxClassInfo *(*t_get_first)(void);
106 t_get_first get_first;
107
108 m_handle = handle;
109
110 // Some system may use a local heap for library.
111 get_first = (t_get_first)GetSymbol("wxGetClassFirst");
112 // It is a wxWindows DLL.
113 if (get_first)
114 PrepareClasses(get_first());
115 }
116
117 wxLibrary::~wxLibrary()
118 {
119 if ( m_handle )
120 {
121 wxDllClose(m_handle);
122 }
123 }
124
125 wxObject *wxLibrary::CreateObject(const wxString& name)
126 {
127 wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
128
129 if (!info)
130 return NULL;
131
132 return info->CreateObject();
133 }
134
135 void wxLibrary::PrepareClasses(wxClassInfo *first)
136 {
137 // Index all class infos by their class name
138 wxClassInfo *info = first;
139 while (info)
140 {
141 if (info->m_className)
142 classTable.Put(info->m_className, (wxObject *)info);
143 info = info->GetNext();
144 }
145
146 // Set base pointers for each wxClassInfo
147 info = first;
148 while (info)
149 {
150 if (info->GetBaseClassName1())
151 info->m_baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
152 if (info->GetBaseClassName2())
153 info->m_baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
154 info = info->m_next;
155 }
156 }
157
158 void *wxLibrary::GetSymbol(const wxString& symbname)
159 {
160 void *symbol = NULL; // return value
161
162 #if defined( __WXMAC__ )
163 Ptr symAddress ;
164 CFragSymbolClass symClass ;
165 Str255 symName ;
166
167 strcpy( (char*) symName , symbname ) ;
168 c2pstr( (char*) symName ) ;
169
170 if ( FindSymbol( m_handle , symName , &symAddress , &symClass ) == noErr )
171 {
172 symbol = (void *)symAddress ;
173 }
174 #else
175 // VZ: hmm... why is WXSTRINGCAST needed? if it's really modified, we
176 // should make a copy of it
177 symbol = wxDllGetSymbol(m_handle, WXSTRINGCAST symbname);
178 #endif
179
180 if ( !symbol )
181 {
182 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
183 symbname.c_str());
184 }
185
186 return symbol;
187 }
188
189 // ---------------------------------------------------------------------------
190 // wxLibraries (only one instance should normally exist)
191 // ---------------------------------------------------------------------------
192
193 wxLibraries::wxLibraries()
194 {
195 }
196
197 wxLibraries::~wxLibraries()
198 {
199 wxNode *node = m_loaded.First();
200
201 while (node) {
202 wxLibrary *lib = (wxLibrary *)node->Data();
203 delete lib;
204
205 node = node->Next();
206 }
207 }
208
209 wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
210 {
211 wxNode *node;
212 wxLibrary *lib;
213 wxClassInfo *old_sm_first;
214
215 if ( (node = m_loaded.Find(name.GetData())) )
216 return ((wxLibrary *)node->Data());
217
218 // If DLL shares data, this is necessary.
219 old_sm_first = wxClassInfo::sm_first;
220 wxClassInfo::sm_first = NULL;
221
222 wxString lib_name = ConstructLibraryName(name);
223
224 #if defined(__UNIX__)
225 // found the first file in LD_LIBRARY_PATH with this name
226 wxString libPath("/lib:/usr/lib"); // system path first
227 const char *envLibPath = getenv("LD_LIBRARY_PATH");
228 if ( envLibPath )
229 libPath << ':' << envLibPath;
230 wxStringTokenizer tokenizer(libPath, ':');
231 while ( tokenizer.HasMoreToken() )
232 {
233 wxString fullname(tokenizer.NextToken());
234
235 fullname << '/' << lib_name;
236 if ( wxFileExists(fullname) )
237 {
238 lib_name = fullname;
239
240 // found the library
241 break;
242 }
243 }
244 //else: not found in the path, leave the name as is (secutiry risk?)
245
246 #endif // __UNIX__
247
248 wxDllType handle;
249
250 #if defined(__WXMAC__)
251 FSSpec myFSSpec ;
252 Ptr myMainAddr ;
253 Str255 myErrName ;
254
255 wxMacPathToFSSpec( lib_name , &myFSSpec ) ;
256 if (GetDiskFragment( &myFSSpec , 0 , kCFragGoesToEOF , "\p" , kPrivateCFragCopy , &handle , &myMainAddr ,
257 myErrName ) != noErr )
258 {
259 p2cstr( myErrName ) ;
260 wxASSERT_MSG( 1 , (char*)myErrName ) ;
261 return NULL ;
262 }
263 #else // !Mac
264 handle = wxDllOpen(lib_name);
265 #endif // OS
266
267 if ( !handle )
268 {
269 wxLogSysError(_("Failed to load shared library '%s'"),
270 lib_name.c_str());
271
272 return NULL;
273 }
274
275 lib = new wxLibrary(handle);
276
277 wxClassInfo::sm_first = old_sm_first;
278
279 m_loaded.Append(name.GetData(), lib);
280
281 return lib;
282 }
283
284 wxObject *wxLibraries::CreateObject(const wxString& path)
285 {
286 wxNode *node = m_loaded.First();
287 wxObject *obj;
288
289 while (node) {
290 obj = ((wxLibrary *)node->Data())->CreateObject(path);
291 if (obj)
292 return obj;
293
294 node = node->Next();
295 }
296 return NULL;
297 }
298
299 #endif // wxUSE_DYNLIB_CLASS