1///////////////////////////////////////////////////////////////////////////// 2// Name: src/common/dynlib.cpp 3// Purpose: Dynamic library management 4// Author: Guilhem Lavaux 5// Modified by: 6// Created: 20/07/98 7// RCS-ID: $Id: dynlib.cpp 41807 2006-10-09 15:58:56Z VZ $ 8// Copyright: (c) 1998 Guilhem Lavaux 9// 2000-2005 Vadim Zeitlin 10// Licence: wxWindows licence 11///////////////////////////////////////////////////////////////////////////// 12 13//FIXME: This class isn't really common at all, it should be moved into 14// platform dependent files (already done for Windows and Unix) 15 16// ============================================================================ 17// declarations 18// ============================================================================ 19 20// ---------------------------------------------------------------------------- 21// headers 22// ---------------------------------------------------------------------------- 23 24#include "wx/wxprec.h" 25 26#ifdef __BORLANDC__ 27 #pragma hdrstop 28#endif 29 30#if wxUSE_DYNLIB_CLASS 31 32#include "wx/dynlib.h" 33 34#ifndef WX_PRECOMP 35 #include "wx/intl.h" 36 #include "wx/log.h" 37 #include "wx/app.h" 38 #include "wx/utils.h" 39#endif //WX_PRECOMP 40 41#include "wx/filefn.h" 42#include "wx/filename.h" // for SplitPath() 43#include "wx/platinfo.h" 44 45#include "wx/arrimpl.cpp" 46 47#if defined(__WXMAC__) 48 #include "wx/mac/private.h" 49#endif 50 51WX_DEFINE_USER_EXPORTED_OBJARRAY(wxDynamicLibraryDetailsArray) 52 53// ============================================================================ 54// implementation 55// ============================================================================ 56 57// --------------------------------------------------------------------------- 58// wxDynamicLibrary 59// --------------------------------------------------------------------------- 60 61#if defined(__WXPM__) || defined(__EMX__) 62 const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll"); 63#elif defined(__WXMAC__) && !defined(__DARWIN__) 64 const wxChar *wxDynamicLibrary::ms_dllext = wxEmptyString; 65#endif 66 67// for MSW/Unix it is defined in platform-specific file 68#if !(defined(__WXMSW__) || defined(__UNIX__)) || defined(__EMX__) 69 70wxDllType wxDynamicLibrary::GetProgramHandle() 71{ 72 wxFAIL_MSG( wxT("GetProgramHandle() is not implemented under this platform")); 73 return 0; 74} 75 76#endif // __WXMSW__ || __UNIX__ 77 78 79bool wxDynamicLibrary::Load(const wxString& libnameOrig, int flags) 80{ 81 wxASSERT_MSG(m_handle == 0, _T("Library already loaded.")); 82 83 // add the proper extension for the DLL ourselves unless told not to 84 wxString libname = libnameOrig; 85 if ( !(flags & wxDL_VERBATIM) ) 86 { 87 // and also check that the libname doesn't already have it 88 wxString ext; 89 wxFileName::SplitPath(libname, NULL, NULL, &ext); 90 if ( ext.empty() ) 91 { 92 libname += GetDllExt(); 93 } 94 } 95 96 // different ways to load a shared library 97 // 98 // FIXME: should go to the platform-specific files! 99#if defined(__WXMAC__) && !defined(__DARWIN__) 100 FSSpec myFSSpec; 101 Ptr myMainAddr; 102 Str255 myErrName; 103 104 wxMacFilename2FSSpec( libname , &myFSSpec ); 105 106 if( GetDiskFragment( &myFSSpec, 107 0, 108 kCFragGoesToEOF, 109 "\p", 110 kPrivateCFragCopy, 111 &m_handle, 112 &myMainAddr, 113 myErrName ) != noErr ) 114 { 115 wxLogSysError( _("Failed to load shared library '%s' Error '%s'"), 116 libname.c_str(), 117 wxMacMakeStringFromPascal( myErrName ).c_str() ); 118 m_handle = 0; 119 } 120 121#elif defined(__WXPM__) || defined(__EMX__) 122 char err[256] = ""; 123 DosLoadModule(err, sizeof(err), (PSZ)libname.c_str(), &m_handle); 124#else // this should be the only remaining branch eventually 125 m_handle = RawLoad(libname, flags); 126#endif 127 128 if ( m_handle == 0 ) 129 { 130#ifdef wxHAVE_DYNLIB_ERROR 131 Error(); 132#else 133 wxLogSysError(_("Failed to load shared library '%s'"), libname.c_str()); 134#endif 135 } 136 137 return IsLoaded(); 138} 139 140// for MSW and Unix this is implemented in the platform-specific file 141// 142// TODO: move the rest to os2/dlpm.cpp and mac/dlmac.cpp! 143#if (!defined(__WXMSW__) && !defined(__UNIX__)) || defined(__EMX__) 144 145/* static */ 146void wxDynamicLibrary::Unload(wxDllType handle) 147{ 148#if defined(__OS2__) || defined(__EMX__) 149 DosFreeModule( handle ); 150#elif defined(__WXMAC__) && !defined(__DARWIN__) 151 CloseConnection( (CFragConnectionID*) &handle ); 152#else 153 #error "runtime shared lib support not implemented" 154#endif 155} 156 157#endif // !(__WXMSW__ || __UNIX__) 158 159void *wxDynamicLibrary::DoGetSymbol(const wxString &name, bool *success) const 160{ 161 wxCHECK_MSG( IsLoaded(), NULL, 162 _T("Can't load symbol from unloaded library") ); 163 164 void *symbol = 0; 165 166 wxUnusedVar(symbol); 167#if defined(__WXMAC__) && !defined(__DARWIN__) 168 Ptr symAddress; 169 CFragSymbolClass symClass; 170 Str255 symName; 171#if TARGET_CARBON 172 c2pstrcpy( (StringPtr) symName, name.fn_str() ); 173#else 174 strcpy( (char *)symName, name.fn_str() ); 175 c2pstr( (char *)symName ); 176#endif 177 if( FindSymbol( m_handle, symName, &symAddress, &symClass ) == noErr ) 178 symbol = (void *)symAddress; 179#elif defined(__WXPM__) || defined(__EMX__) 180 DosQueryProcAddr( m_handle, 1L, (PSZ)name.c_str(), (PFN*)symbol ); 181#else 182 symbol = RawGetSymbol(m_handle, name); 183#endif 184 185 if ( success ) 186 *success = symbol != NULL; 187 188 return symbol; 189} 190 191void *wxDynamicLibrary::GetSymbol(const wxString& name, bool *success) const 192{ 193 void *symbol = DoGetSymbol(name, success); 194 if ( !symbol ) 195 { 196#ifdef wxHAVE_DYNLIB_ERROR 197 Error(); 198#else 199 wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"), 200 name.c_str()); 201#endif 202 } 203 204 return symbol; 205} 206 207// ---------------------------------------------------------------------------- 208// informational methods 209// ---------------------------------------------------------------------------- 210 211/*static*/ 212wxString 213wxDynamicLibrary::CanonicalizeName(const wxString& name, 214 wxDynamicLibraryCategory cat) 215{ 216 wxString nameCanonic; 217 218 // under Unix the library names usually start with "lib" prefix, add it 219#if defined(__UNIX__) && !defined(__EMX__) 220 switch ( cat ) 221 { 222 default: 223 wxFAIL_MSG( _T("unknown wxDynamicLibraryCategory value") ); 224 // fall through 225 226 case wxDL_MODULE: 227 // don't do anything for modules, their names are arbitrary 228 break; 229 230 case wxDL_LIBRARY: 231 // library names should start with "lib" under Unix 232 nameCanonic = _T("lib"); 233 break; 234 } 235#else // !__UNIX__ 236 wxUnusedVar(cat); 237#endif // __UNIX__/!__UNIX__ 238 239 nameCanonic << name << GetDllExt(); 240 return nameCanonic; 241} 242 243/*static*/ 244wxString wxDynamicLibrary::CanonicalizePluginName(const wxString& name, 245 wxPluginCategory cat) 246{ 247 wxString suffix; 248 if ( cat == wxDL_PLUGIN_GUI ) 249 { 250 suffix = wxPlatformInfo::Get().GetPortIdShortName(); 251 } 252#if wxUSE_UNICODE 253 suffix << _T('u'); 254#endif 255#ifdef __WXDEBUG__ 256 suffix << _T('d'); 257#endif 258 259 if ( !suffix.empty() ) 260 suffix = wxString(_T("_")) + suffix; 261 262#define WXSTRINGIZE(x) #x 263#if defined(__UNIX__) && !defined(__EMX__) 264 #if (wxMINOR_VERSION % 2) == 0 265 #define wxDLLVER(x,y,z) "-" WXSTRINGIZE(x) "." WXSTRINGIZE(y) 266 #else 267 #define wxDLLVER(x,y,z) "-" WXSTRINGIZE(x) "." WXSTRINGIZE(y) "." WXSTRINGIZE(z) 268 #endif 269#else 270 #if (wxMINOR_VERSION % 2) == 0 271 #define wxDLLVER(x,y,z) WXSTRINGIZE(x) WXSTRINGIZE(y) 272 #else 273 #define wxDLLVER(x,y,z) WXSTRINGIZE(x) WXSTRINGIZE(y) WXSTRINGIZE(z) 274 #endif 275#endif 276 277 suffix << wxString::FromAscii(wxDLLVER(wxMAJOR_VERSION, wxMINOR_VERSION, 278 wxRELEASE_NUMBER)); 279#undef wxDLLVER 280#undef WXSTRINGIZE 281 282#ifdef __WINDOWS__ 283 // Add compiler identification: 284 #if defined(__GNUG__) 285 suffix << _T("_gcc"); 286 #elif defined(__VISUALC__) 287 suffix << _T("_vc"); 288 #elif defined(__WATCOMC__) 289 suffix << _T("_wat"); 290 #elif defined(__BORLANDC__) 291 suffix << _T("_bcc"); 292 #endif 293#endif 294 295 return CanonicalizeName(name + suffix, wxDL_MODULE); 296} 297 298/*static*/ 299wxString wxDynamicLibrary::GetPluginsDirectory() 300{ 301#ifdef __UNIX__ 302 wxString format = wxGetInstallPrefix(); 303 wxString dir; 304 format << wxFILE_SEP_PATH 305 << wxT("lib") << wxFILE_SEP_PATH 306 << wxT("wx") << wxFILE_SEP_PATH 307#if (wxMINOR_VERSION % 2) == 0 308 << wxT("%i.%i"); 309 dir.Printf(format.c_str(), wxMAJOR_VERSION, wxMINOR_VERSION); 310#else 311 << wxT("%i.%i.%i"); 312 dir.Printf(format.c_str(), 313 wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER); 314#endif 315 return dir; 316 317#else // ! __UNIX__ 318 return wxEmptyString; 319#endif 320} 321 322 323#endif // wxUSE_DYNLIB_CLASS 324