]> git.saurik.com Git - wxWidgets.git/blob - src/common/dynlib.cpp
quick compilation fix for wxBase
[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 licence
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
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 #include "wx/utils.h"
41 #include "wx/filename.h" // for SplitPath()
42
43 #if defined(__WXMAC__)
44 #include "wx/mac/private.h"
45 #endif
46
47
48 // ============================================================================
49 // implementation
50 // ============================================================================
51
52 #if defined(__DARWIN__)
53 // ---------------------------------------------------------------------------
54 // For Darwin/Mac OS X
55 // supply the sun style dlopen functions in terms of Darwin NS*
56 // ---------------------------------------------------------------------------
57
58 /* Porting notes:
59 * The dlopen port is a port from dl_next.xs by Anno Siegel.
60 * dl_next.xs is itself a port from dl_dlopen.xs by Paul Marquess.
61 * The method used here is just to supply the sun style dlopen etc.
62 * functions in terms of Darwin NS*.
63 */
64
65 #include <stdio.h>
66 #include <mach-o/dyld.h>
67
68 static char dl_last_error[1024];
69
70 static
71 void TranslateError(const char *path, int number)
72 {
73 unsigned int index;
74 static char *OFIErrorStrings[] =
75 {
76 "%s(%d): Object Image Load Failure\n",
77 "%s(%d): Object Image Load Success\n",
78 "%s(%d): Not an recognisable object file\n",
79 "%s(%d): No valid architecture\n",
80 "%s(%d): Object image has an invalid format\n",
81 "%s(%d): Invalid access (permissions?)\n",
82 "%s(%d): Unknown error code from NSCreateObjectFileImageFromFile\n",
83 };
84 #define NUM_OFI_ERRORS (sizeof(OFIErrorStrings) / sizeof(OFIErrorStrings[0]))
85
86 index = number;
87 if (index > NUM_OFI_ERRORS - 1) {
88 index = NUM_OFI_ERRORS - 1;
89 }
90 sprintf(dl_last_error, OFIErrorStrings[index], path, number);
91 }
92
93 const char *dlerror()
94 {
95 return dl_last_error;
96 }
97
98 void *dlopen(const char *path, int WXUNUSED(mode) /* mode is ignored */)
99 {
100 int dyld_result;
101 NSObjectFileImage ofile;
102 NSModule handle = NULL;
103
104 dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
105 if (dyld_result != NSObjectFileImageSuccess)
106 {
107 TranslateError(path, dyld_result);
108 }
109 else
110 {
111 // NSLinkModule will cause the run to abort on any link error's
112 // not very friendly but the error recovery functionality is limited.
113 handle = NSLinkModule(ofile, path, NSLINKMODULE_OPTION_BINDNOW);
114 }
115
116 return handle;
117 }
118
119 int dlclose(void *handle)
120 {
121 NSUnLinkModule( handle, NSUNLINKMODULE_OPTION_NONE);
122 return 0;
123 }
124
125 void *dlsym(void *handle, const char *symbol)
126 {
127 void *addr;
128
129 NSSymbol nsSymbol = NSLookupSymbolInModule( handle , symbol ) ;
130
131 if ( nsSymbol)
132 {
133 addr = NSAddressOfSymbol(nsSymbol);
134 }
135 else
136 {
137 addr = NULL;
138 }
139 return addr;
140 }
141
142 #endif // defined(__DARWIN__)
143
144
145 // ---------------------------------------------------------------------------
146 // wxDynamicLibrary
147 // ---------------------------------------------------------------------------
148
149 //FIXME: This class isn't really common at all, it should be moved into
150 // platform dependent files.
151
152 #if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
153 const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll");
154 #elif defined(__UNIX__)
155 #if defined(__HPUX__)
156 const wxChar *wxDynamicLibrary::ms_dllext = _T(".sl");
157 #else
158 const wxChar *wxDynamicLibrary::ms_dllext = _T(".so");
159 #endif
160 #endif
161
162 wxDllType wxDynamicLibrary::GetProgramHandle()
163 {
164 #if defined( HAVE_DLOPEN ) && !defined(__EMX__)
165 return dlopen(0, RTLD_LAZY);
166 #elif defined (HAVE_SHL_LOAD)
167 return PROG_HANDLE;
168 #else
169 wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
170 return 0;
171 #endif
172 }
173
174 bool wxDynamicLibrary::Load(wxString libname, int flags)
175 {
176 wxASSERT_MSG(m_handle == 0, _T("Library already loaded."));
177
178 // add the proper extension for the DLL ourselves unless told not to
179 if ( !(flags & wxDL_VERBATIM) )
180 {
181 // and also check that the libname doesn't already have it
182 wxString ext;
183 wxFileName::SplitPath(libname, NULL, NULL, &ext);
184 if ( ext.empty() )
185 {
186 libname += GetDllExt();
187 }
188 }
189
190 // different ways to load a shared library
191 //
192 // FIXME: should go to the platform-specific files!
193 #if defined(__WXMAC__) && !defined(__DARWIN__)
194 FSSpec myFSSpec;
195 Ptr myMainAddr;
196 Str255 myErrName;
197
198 wxMacFilename2FSSpec( libname , &myFSSpec );
199
200 if( GetDiskFragment( &myFSSpec,
201 0,
202 kCFragGoesToEOF,
203 "\p",
204 kPrivateCFragCopy,
205 &m_handle,
206 &myMainAddr,
207 myErrName ) != noErr )
208 {
209 p2cstr( myErrName );
210 wxLogSysError( _("Failed to load shared library '%s' Error '%s'"),
211 libname.c_str(),
212 (char*)myErrName );
213 m_handle = 0;
214 }
215
216 #elif defined(__WXPM__) || defined(__EMX__)
217 char err[256] = "";
218 DosLoadModule(err, sizeof(err), libname.c_str(), &m_handle);
219
220 #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
221
222 #if defined(__VMS) || defined(__DARWIN__)
223 m_handle = dlopen(libname.c_str(), 0); // The second parameter is ignored
224 #else // !__VMS && !__DARWIN__
225 int rtldFlags = 0;
226
227 if ( flags & wxDL_LAZY )
228 {
229 wxASSERT_MSG( (flags & wxDL_NOW) == 0,
230 _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
231 #ifdef RTLD_LAZY
232 rtldFlags |= RTLD_LAZY;
233 #else
234 wxLogDebug(_T("wxDL_LAZY is not supported on this platform"));
235 #endif
236 }
237 else if ( flags & wxDL_NOW )
238 {
239 #ifdef RTLD_NOW
240 rtldFlags |= RTLD_NOW;
241 #else
242 wxLogDebug(_T("wxDL_NOW is not supported on this platform"));
243 #endif
244 }
245
246 if ( flags & wxDL_GLOBAL )
247 {
248 #ifdef RTLD_GLOBAL
249 rtldFlags |= RTLD_GLOBAL;
250 #else
251 wxLogDebug(_T("RTLD_GLOBAL is not supported on this platform."));
252 #endif
253 }
254
255 m_handle = dlopen(libname.fn_str(), rtldFlags);
256 #endif // __VMS || __DARWIN__ ?
257
258 #elif defined(HAVE_SHL_LOAD)
259 int shlFlags = 0;
260
261 if( flags & wxDL_LAZY )
262 {
263 wxASSERT_MSG( (flags & wxDL_NOW) == 0,
264 _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
265 shlFlags |= BIND_DEFERRED;
266 }
267 else if( flags & wxDL_NOW )
268 {
269 shlFlags |= BIND_IMMEDIATE;
270 }
271 m_handle = shl_load(libname.fn_str(), BIND_DEFERRED, 0);
272
273 #elif defined(__WINDOWS__)
274 m_handle = ::LoadLibrary(libname.c_str());
275 #else
276 #error "runtime shared lib support not implemented on this platform"
277 #endif
278
279 if ( m_handle == 0 )
280 {
281 wxString msg(_("Failed to load shared library '%s'"));
282 #if defined(HAVE_DLERROR) && !defined(__EMX__)
283
284 #if wxUSE_UNICODE
285 wxWCharBuffer buffer = wxConvLocal.cMB2WC( dlerror() );
286 const wxChar *err = buffer;
287 #else
288 const wxChar *err = dlerror();
289 #endif
290
291 if( err )
292 wxLogError( msg, err );
293 #else
294 wxLogSysError( msg, libname.c_str() );
295 #endif
296 }
297
298 return IsLoaded();
299 }
300
301 void wxDynamicLibrary::Unload()
302 {
303 if( IsLoaded() )
304 {
305 #if defined(__WXPM__) || defined(__EMX__)
306 DosFreeModule( m_handle );
307 #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
308 dlclose( m_handle );
309 #elif defined(HAVE_SHL_LOAD)
310 shl_unload( m_handle );
311 #elif defined(__WINDOWS__)
312 ::FreeLibrary( m_handle );
313 #elif defined(__WXMAC__) && !defined(__DARWIN__)
314 CloseConnection( (CFragConnectionID*) &m_handle );
315 #else
316 #error "runtime shared lib support not implemented"
317 #endif
318 m_handle = 0;
319 }
320 }
321
322 void *wxDynamicLibrary::GetSymbol(const wxString &name, bool *success) const
323 {
324 wxCHECK_MSG( IsLoaded(), NULL,
325 _T("Can't load symbol from unloaded library") );
326
327 bool failed = FALSE;
328 void *symbol = 0;
329
330 #if defined(__WXMAC__) && !defined(__DARWIN__)
331 Ptr symAddress;
332 CFragSymbolClass symClass;
333 Str255 symName;
334 #if TARGET_CARBON
335 c2pstrcpy( (StringPtr) symName, name );
336 #else
337 strcpy( (char *)symName, name );
338 c2pstr( (char *)symName );
339 #endif
340 if( FindSymbol( dllHandle, symName, &symAddress, &symClass ) == noErr )
341 symbol = (void *)symAddress;
342
343 #elif defined(__WXPM__) || defined(__EMX__)
344 DosQueryProcAddr( m_handle, 1L, name.c_str(), (PFN*)symbol );
345
346 #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
347 symbol = dlsym( m_handle, name.fn_str() );
348
349 #elif defined(HAVE_SHL_LOAD)
350 // use local variable since shl_findsym modifies the handle argument
351 // to indicate where the symbol was found (GD)
352 wxDllType the_handle = m_handle;
353 if( shl_findsym( &the_handle, name.fn_str(), TYPE_UNDEFINED, &symbol ) != 0 )
354 symbol = 0;
355
356 #elif defined(__WINDOWS__)
357 symbol = (void*) ::GetProcAddress( m_handle, name.mb_str() );
358
359 #else
360 #error "runtime shared lib support not implemented"
361 #endif
362
363 if ( !symbol )
364 {
365 #if defined(HAVE_DLERROR) && !defined(__EMX__)
366
367 #if wxUSE_UNICODE
368 wxWCharBuffer buffer = wxConvLocal.cMB2WC( dlerror() );
369 const wxChar *err = buffer;
370 #else
371 const wxChar *err = dlerror();
372 #endif
373
374 if( err )
375 {
376 wxLogError(wxT("%s"), err);
377 }
378 #else
379 failed = TRUE;
380 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
381 name.c_str());
382 #endif
383 }
384 if( success )
385 *success = !failed;
386
387 return symbol;
388 }
389
390
391 /*static*/
392 wxString wxDynamicLibrary::CanonicalizeName(const wxString& name,
393 wxDynamicLibraryCategory cat)
394 {
395 #ifdef __UNIX__
396 if ( cat == wxDL_MODULE )
397 return name + GetDllExt();
398 else
399 return wxString(_T("lib")) + name + GetDllExt();
400 #else
401 return name + GetDllExt();
402 #endif
403 }
404
405 /*static*/
406 wxString wxDynamicLibrary::CanonicalizePluginName(const wxString& name,
407 wxPluginCategory cat)
408 {
409 wxString suffix;
410 if ( cat == wxDL_PLUGIN_GUI )
411 {
412 suffix = wxString::FromAscii(
413 #if defined(__WXMSW__)
414 "msw"
415 #elif defined(__WXGTK__)
416 "gtk"
417 #elif defined(__WXMGL__)
418 "mgl"
419 #elif defined(__WXMOTIF__)
420 "motif"
421 #elif defined(__WXOS2__)
422 "pm"
423 #elif defined(__WXX11__)
424 "x11"
425 #elif defined(__WXMAC__)
426 "mac"
427 #elif defined(__WXCOCOA__)
428 "cocoa"
429 #else // FIXME - wrong!
430 ""
431 #endif
432 );
433
434 #ifdef __WXUNIVERSAL__
435 suffix << _T("univ");
436 #endif
437 }
438 #if wxUSE_UNICODE
439 suffix << _T('u');
440 #endif
441 #ifdef __WXDEBUG__
442 suffix << _T('d');
443 #endif
444
445 if ( !suffix.empty() )
446 suffix = wxString(_T("_")) + suffix;
447
448 #ifdef __UNIX__
449 #if (wxMINOR_VERSION % 2) == 0
450 #define wxDLLVER(x,y,z) "-" #x "." #y
451 #else
452 #define wxDLLVER(x,y,z) "-" #x "." #y "." #z
453 #endif
454 #else
455 #if (wxMINOR_VERSION % 2) == 0
456 #define wxDLLVER(x,y,z) #x #y
457 #else
458 #define wxDLLVER(x,y,z) #x #y #z
459 #endif
460 #endif
461 suffix << wxString::FromAscii(wxDLLVER(wxMAJOR_VERSION, wxMINOR_VERSION,
462 wxRELEASE_NUMBER));
463 #undef wxDLLVER
464
465 return CanonicalizeName(name + suffix, wxDL_MODULE);
466 }
467
468 /*static*/
469 wxString wxDynamicLibrary::GetPluginsDirectory()
470 {
471 #ifdef __UNIX__
472 wxString format = wxGetInstallPrefix();
473 format << wxFILE_SEP_PATH
474 << wxT("lib") << wxFILE_SEP_PATH
475 << wxT("wx") << wxFILE_SEP_PATH
476 << wxT("%i.%i");
477 wxString dir;
478 dir.Printf(format.c_str(), wxMAJOR_VERSION, wxMINOR_VERSION);
479 return dir;
480 #else
481 return wxEmptyString;
482 #endif
483 }
484
485
486 #endif // wxUSE_DYNLIB_CLASS