1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Dynamic library management
4 // Author: Guilhem Lavaux
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 # pragma implementation "dynlib.h"
24 #include "wx/wxprec.h"
30 #if wxUSE_DYNLIB_CLASS
32 #if defined(__WINDOWS__)
33 #include "wx/msw/private.h"
36 #include "wx/dynlib.h"
37 #include "wx/filefn.h"
41 #include "wx/filename.h" // for SplitPath()
43 #if defined(__WXMAC__)
44 #include "wx/mac/private.h"
48 // ============================================================================
50 // ============================================================================
52 #if defined(__DARWIN__)
53 // ---------------------------------------------------------------------------
54 // For Darwin/Mac OS X
55 // supply the sun style dlopen functions in terms of Darwin NS*
56 // ---------------------------------------------------------------------------
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*.
66 #include <mach-o/dyld.h>
68 static char dl_last_error
[1024];
71 void TranslateError(const char *path
, int number
)
74 static char *OFIErrorStrings
[] =
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",
84 #define NUM_OFI_ERRORS (sizeof(OFIErrorStrings) / sizeof(OFIErrorStrings[0]))
87 if (index
> NUM_OFI_ERRORS
- 1) {
88 index
= NUM_OFI_ERRORS
- 1;
90 sprintf(dl_last_error
, OFIErrorStrings
[index
], path
, number
);
98 void *dlopen(const char *path
, int WXUNUSED(mode
) /* mode is ignored */)
101 NSObjectFileImage ofile
;
102 NSModule handle
= NULL
;
104 dyld_result
= NSCreateObjectFileImageFromFile(path
, &ofile
);
105 if (dyld_result
!= NSObjectFileImageSuccess
)
107 TranslateError(path
, dyld_result
);
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
);
119 int dlclose(void *handle
)
121 NSUnLinkModule( handle
, NSUNLINKMODULE_OPTION_NONE
);
125 void *dlsym(void *handle
, const char *symbol
)
129 NSSymbol nsSymbol
= NSLookupSymbolInModule( handle
, symbol
) ;
133 addr
= NSAddressOfSymbol(nsSymbol
);
142 #endif // defined(__DARWIN__)
145 // ---------------------------------------------------------------------------
147 // ---------------------------------------------------------------------------
149 //FIXME: This class isn't really common at all, it should be moved into
150 // platform dependent files.
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");
158 const wxChar
*wxDynamicLibrary::ms_dllext
= _T(".so");
162 wxDllType
wxDynamicLibrary::GetProgramHandle()
164 #if defined( HAVE_DLOPEN ) && !defined(__EMX__)
165 return dlopen(0, RTLD_LAZY
);
166 #elif defined (HAVE_SHL_LOAD)
169 wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
174 bool wxDynamicLibrary::Load(wxString libname
, int flags
)
176 wxASSERT_MSG(m_handle
== 0, _T("Library already loaded."));
178 // add the proper extension for the DLL ourselves unless told not to
179 if ( !(flags
& wxDL_VERBATIM
) )
181 // and also check that the libname doesn't already have it
183 wxFileName::SplitPath(libname
, NULL
, NULL
, &ext
);
186 libname
+= GetDllExt();
190 // different ways to load a shared library
192 // FIXME: should go to the platform-specific files!
193 #if defined(__WXMAC__) && !defined(__DARWIN__)
198 wxMacFilename2FSSpec( libname
, &myFSSpec
);
200 if( GetDiskFragment( &myFSSpec
,
207 myErrName
) != noErr
)
210 wxLogSysError( _("Failed to load shared library '%s' Error '%s'"),
216 #elif defined(__WXPM__) || defined(__EMX__)
218 DosLoadModule(err
, sizeof(err
), libname
.c_str(), &m_handle
);
220 #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
222 #if defined(__VMS) || defined(__DARWIN__)
223 m_handle
= dlopen(libname
.c_str(), 0); // The second parameter is ignored
224 #else // !__VMS && !__DARWIN__
227 if ( flags
& wxDL_LAZY
)
229 wxASSERT_MSG( (flags
& wxDL_NOW
) == 0,
230 _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
232 rtldFlags
|= RTLD_LAZY
;
234 wxLogDebug(_T("wxDL_LAZY is not supported on this platform"));
237 else if ( flags
& wxDL_NOW
)
240 rtldFlags
|= RTLD_NOW
;
242 wxLogDebug(_T("wxDL_NOW is not supported on this platform"));
246 if ( flags
& wxDL_GLOBAL
)
249 rtldFlags
|= RTLD_GLOBAL
;
251 wxLogDebug(_T("RTLD_GLOBAL is not supported on this platform."));
255 m_handle
= dlopen(libname
.fn_str(), rtldFlags
);
256 #endif // __VMS || __DARWIN__ ?
258 #elif defined(HAVE_SHL_LOAD)
261 if( flags
& wxDL_LAZY
)
263 wxASSERT_MSG( (flags
& wxDL_NOW
) == 0,
264 _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
265 shlFlags
|= BIND_DEFERRED
;
267 else if( flags
& wxDL_NOW
)
269 shlFlags
|= BIND_IMMEDIATE
;
271 m_handle
= shl_load(libname
.fn_str(), BIND_DEFERRED
, 0);
273 #elif defined(__WINDOWS__)
274 m_handle
= ::LoadLibrary(libname
.c_str());
276 #error "runtime shared lib support not implemented on this platform"
281 wxString
msg(_("Failed to load shared library '%s'"));
282 #if defined(HAVE_DLERROR) && !defined(__EMX__)
285 wxWCharBuffer buffer
= wxConvLocal
.cMB2WC( dlerror() );
286 const wxChar
*err
= buffer
;
288 const wxChar
*err
= dlerror();
292 wxLogError( msg
, err
);
294 wxLogSysError( msg
, libname
.c_str() );
301 void wxDynamicLibrary::Unload()
305 #if defined(__WXPM__) || defined(__EMX__)
306 DosFreeModule( m_handle
);
307 #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
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
);
316 #error "runtime shared lib support not implemented"
322 void *wxDynamicLibrary::GetSymbol(const wxString
&name
, bool *success
) const
324 wxCHECK_MSG( IsLoaded(), NULL
,
325 _T("Can't load symbol from unloaded library") );
330 #if defined(__WXMAC__) && !defined(__DARWIN__)
332 CFragSymbolClass symClass
;
335 c2pstrcpy( (StringPtr
) symName
, name
);
337 strcpy( (char *)symName
, name
);
338 c2pstr( (char *)symName
);
340 if( FindSymbol( dllHandle
, symName
, &symAddress
, &symClass
) == noErr
)
341 symbol
= (void *)symAddress
;
343 #elif defined(__WXPM__) || defined(__EMX__)
344 DosQueryProcAddr( m_handle
, 1L, name
.c_str(), (PFN
*)symbol
);
346 #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
347 symbol
= dlsym( m_handle
, name
.fn_str() );
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 )
356 #elif defined(__WINDOWS__)
357 symbol
= (void*) ::GetProcAddress( m_handle
, name
.mb_str() );
360 #error "runtime shared lib support not implemented"
365 #if defined(HAVE_DLERROR) && !defined(__EMX__)
368 wxWCharBuffer buffer
= wxConvLocal
.cMB2WC( dlerror() );
369 const wxChar
*err
= buffer
;
371 const wxChar
*err
= dlerror();
376 wxLogError(wxT("%s"), err
);
380 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
392 wxString
wxDynamicLibrary::CanonicalizeName(const wxString
& name
,
393 wxDynamicLibraryCategory cat
)
396 if ( cat
== wxDL_MODULE
)
397 return name
+ GetDllExt();
399 return wxString(_T("lib")) + name
+ GetDllExt();
401 return name
+ GetDllExt();
406 wxString
wxDynamicLibrary::CanonicalizePluginName(const wxString
& name
,
407 wxPluginCategory cat
)
410 if ( cat
== wxDL_PLUGIN_GUI
)
412 suffix
= wxString::FromAscii(
413 #if defined(__WXMSW__)
415 #elif defined(__WXGTK__)
417 #elif defined(__WXMGL__)
419 #elif defined(__WXMOTIF__)
421 #elif defined(__WXOS2__)
423 #elif defined(__WXX11__)
425 #elif defined(__WXMAC__)
427 #elif defined(__WXCOCOA__)
429 #else // FIXME - wrong!
434 #ifdef __WXUNIVERSAL__
435 suffix
<< _T("univ");
445 if ( !suffix
.empty() )
446 suffix
= wxString(_T("_")) + suffix
;
449 #if (wxMINOR_VERSION % 2) == 0
450 #define wxDLLVER(x,y,z) "-" #x "." #y
452 #define wxDLLVER(x,y,z) "-" #x "." #y "." #z
455 #if (wxMINOR_VERSION % 2) == 0
456 #define wxDLLVER(x,y,z) #x #y
458 #define wxDLLVER(x,y,z) #x #y #z
461 suffix
<< wxString::FromAscii(wxDLLVER(wxMAJOR_VERSION
, wxMINOR_VERSION
,
465 return CanonicalizeName(name
+ suffix
, wxDL_MODULE
);
469 wxString
wxDynamicLibrary::GetPluginsDirectory()
472 wxString format
= wxGetInstallPrefix();
473 format
<< wxFILE_SEP_PATH
474 << wxT("lib") << wxFILE_SEP_PATH
475 << wxT("wx") << wxFILE_SEP_PATH
478 dir
.Printf(format
.c_str(), wxMAJOR_VERSION
, wxMINOR_VERSION
);
481 return wxEmptyString
;
486 #endif // wxUSE_DYNLIB_CLASS