1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Dynamic library management 
   4 // Author:      Guilhem Lavaux 
   8 // Copyright:   (c) Guilhem Lavaux 
   9 // Licence:     wxWindows license 
  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" 
  40 #include "wx/tokenzr.h" 
  42 // ---------------------------------------------------------------------------- 
  43 // conditional compilation 
  44 // ---------------------------------------------------------------------------- 
  46 #if defined(__WXPM__) || defined(__EMX__) 
  49 #  define wxDllOpen(error, lib, handle)     DosLoadModule(error, sizeof(error), lib, &handle) 
  50 #  define wxDllGetSymbol(handle, modaddr)   DosQueryProcAddr(handle, 1L, NULL, (PFN*)modaddr) 
  51 #  define wxDllClose(handle)                DosFreeModule(handle) 
  52 #elif defined(HAVE_DLOPEN) 
  53 #   define wxDllOpen(lib)                dlopen(lib.fn_str(), RTLD_NOW/*RTLD_LAZY*/) 
  54 #   define wxDllGetSymbol(handle, name)  dlsym(handle, name) 
  55 #   define wxDllClose                    dlclose 
  56 #elif defined(HAVE_SHL_LOAD) 
  57 #   define wxDllOpen(lib)                shl_load(lib.fn_str(), BIND_DEFERRED, 0) 
  58 #   define wxDllClose      shl_unload 
  60     static inline void *wxDllGetSymbol(shl_t handle
, const wxString
& name
) 
  63         if ( shl_findsym(&handle
, name
.mb_str(), TYPE_UNDEFINED
, &sym
) == 0 ) 
  68 #elif defined(__WINDOWS__) 
  69     // using LoadLibraryEx under Win32 to avoid name clash with LoadLibrary 
  72 #      define wxDllOpen(lib)                  ::LoadLibraryExW(lib, 0, 0) 
  74 #      define wxDllOpen(lib)                  ::LoadLibraryExA(lib, 0, 0) 
  77 #      define wxDllOpen(lib)                  ::LoadLibrary(lib) 
  79 #   define wxDllGetSymbol(handle, name)    ::GetProcAddress(handle, name) 
  80 #   define wxDllClose                      ::FreeLibrary 
  82 #   error "Don't know how to load shared libraries on this platform." 
  85 // --------------------------------------------------------------------------- 
  87 // --------------------------------------------------------------------------- 
  89 wxLibraries wxTheLibraries
; 
  91 // ============================================================================ 
  93 // ============================================================================ 
  95 // construct the full name from the base shared object name: adds a .dll 
  96 // suffix under Windows or .so under Unix 
  97 static wxString 
ConstructLibraryName(const wxString
& basename
) 
 100     fullname 
<< basename 
<< wxDllLoader::GetDllExt(); 
 106 // --------------------------------------------------------------------------- 
 107 // wxLibrary (one instance per dynamic library) 
 108 // --------------------------------------------------------------------------- 
 110 wxLibrary::wxLibrary(wxDllType handle
) 
 112     typedef wxClassInfo 
*(*t_get_first
)(void); 
 113     t_get_first get_first
; 
 117     // Some system may use a local heap for library. 
 118     get_first 
= (t_get_first
)GetSymbol("wxGetClassFirst"); 
 119     // It is a wxWindows DLL. 
 121         PrepareClasses(get_first()); 
 124 wxLibrary::~wxLibrary() 
 128         wxDllClose(m_handle
); 
 132 wxObject 
*wxLibrary::CreateObject(const wxString
& name
) 
 134     wxClassInfo 
*info 
= (wxClassInfo 
*)classTable
.Get(name
); 
 139     return info
->CreateObject(); 
 142 void wxLibrary::PrepareClasses(wxClassInfo 
*first
) 
 144     // Index all class infos by their class name 
 145     wxClassInfo 
*info 
= first
; 
 148         if (info
->m_className
) 
 149             classTable
.Put(info
->m_className
, (wxObject 
*)info
); 
 150         info 
= info
->GetNext(); 
 153     // Set base pointers for each wxClassInfo 
 157         if (info
->GetBaseClassName1()) 
 158             info
->m_baseInfo1 
= (wxClassInfo 
*)classTable
.Get(info
->GetBaseClassName1()); 
 159         if (info
->GetBaseClassName2()) 
 160             info
->m_baseInfo2 
= (wxClassInfo 
*)classTable
.Get(info
->GetBaseClassName2()); 
 165 void *wxLibrary::GetSymbol(const wxString
& symbname
) 
 167    return wxDllLoader::GetSymbol(m_handle
, symbname
); 
 170 // --------------------------------------------------------------------------- 
 172 // --------------------------------------------------------------------------- 
 175 wxString 
wxDllLoader::GetDllExt() 
 179 #if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__) 
 181 #elif defined(__UNIX__) 
 182 #   if defined(__HPUX__) 
 194 wxDllLoader::GetProgramHandle(void) 
 196 #if defined( HAVE_DLOPEN ) && !defined(__EMX__) 
 197    // optain handle for main program 
 198    return dlopen(NULL
, RTLD_NOW
/*RTLD_LAZY*/);  
 199 #elif defined (HAVE_SHL_LOAD) 
 200    // shl_findsymbol with NULL handle looks up in main program 
 203    wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2")); 
 210 wxDllLoader::LoadLibrary(const wxString 
& libname
, bool *success
) 
 214 #if defined(__WXMAC__) 
 219     wxMacPathToFSSpec( libname 
, &myFSSpec 
) ; 
 220     if (GetDiskFragment( &myFSSpec 
, 0 , kCFragGoesToEOF 
, "\p" , kPrivateCFragCopy 
, &handle 
, &myMainAddr 
, 
 221                 myErrName 
) != noErr 
) 
 223         p2cstr( myErrName 
) ; 
 224         wxASSERT_MSG( 1 , (char*)myErrName 
) ; 
 227 #elif defined(__WXPM__) || defined(__EMX__) 
 228     char zError
[256] = ""; 
 229     wxDllOpen(zError
, libname
, handle
); 
 231     handle 
= wxDllOpen(libname
); 
 236         wxString 
msg(_("Failed to load shared library '%s'")); 
 239         const char *errmsg 
= dlerror(); 
 242             // the error string format is "libname: ...", but we already have 
 243             // libname, so cut it off 
 244             const char *p 
= strchr(errmsg
, ':'); 
 256             wxLogError(msg
, libname
.c_str(), p
); 
 259 #endif // HAVE_DLERROR 
 261             wxLogSysError(msg
, libname
.c_str()); 
 267         *success 
= handle 
!= 0; 
 276 wxDllLoader::UnloadLibrary(wxDllType handle
) 
 283 wxDllLoader::GetSymbol(wxDllType dllHandle
, const wxString 
&name
) 
 285     void *symbol 
= NULL
;    // return value 
 287 #if defined( __WXMAC__ ) 
 289     CFragSymbolClass symClass 
; 
 292     strcpy( (char*) symName 
, name 
) ; 
 293     c2pstr( (char*) symName 
) ; 
 295     if ( FindSymbol( dllHandle 
, symName 
, &symAddress 
, &symClass 
) == noErr 
) 
 296         symbol 
= (void *)symAddress 
; 
 297 #elif defined( __WXPM__ ) || defined(__EMX__) 
 298     wxDllGetSymbol(dllHandle
, symbol
); 
 300     // mb_str() is necessary in Unicode build 
 301     symbol 
= wxDllGetSymbol(dllHandle
, name
.mb_str()); 
 306         wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"), 
 312 // --------------------------------------------------------------------------- 
 313 // wxLibraries (only one instance should normally exist) 
 314 // --------------------------------------------------------------------------- 
 316 wxLibraries::wxLibraries():m_loaded(wxKEY_STRING
) 
 320 wxLibraries::~wxLibraries() 
 322     wxNode 
*node 
= m_loaded
.First(); 
 325         wxLibrary 
*lib 
= (wxLibrary 
*)node
->Data(); 
 332 wxLibrary 
*wxLibraries::LoadLibrary(const wxString
& name
) 
 336     wxClassInfo 
*old_sm_first
; 
 338 #if defined(__VISAGECPP__) 
 339     node 
= m_loaded
.Find(name
.GetData()); 
 341         return ((wxLibrary 
*)node
->Data()); 
 343     if ( (node 
= m_loaded
.Find(name
.GetData())) ) 
 344         return ((wxLibrary 
*)node
->Data()); 
 346     // If DLL shares data, this is necessary. 
 347     old_sm_first 
= wxClassInfo::sm_first
; 
 348     wxClassInfo::sm_first 
= NULL
; 
 350     wxString libname 
= ConstructLibraryName(name
); 
 353   Unix automatically builds that library name, at least for dlopen() 
 356 #if defined(__UNIX__) 
 357     // found the first file in LD_LIBRARY_PATH with this name 
 358     wxString 
libPath("/lib:/usr/lib"); // system path first 
 359     const char *envLibPath 
= getenv("LD_LIBRARY_PATH"); 
 361         libPath 
<< wxT(':') << envLibPath
; 
 362     wxStringTokenizer 
tokenizer(libPath
, wxT(':')); 
 363     while ( tokenizer
.HasMoreToken() ) 
 365         wxString 
fullname(tokenizer
.NextToken()); 
 367         fullname 
<< wxT('/') << libname
; 
 368         if ( wxFileExists(fullname
) ) 
 376     //else: not found in the path, leave the name as is (secutiry risk?) 
 381     bool success 
= FALSE
; 
 382     wxDllType handle 
= wxDllLoader::LoadLibrary(libname
, &success
); 
 385        lib 
= new wxLibrary(handle
); 
 386        wxClassInfo::sm_first 
= old_sm_first
; 
 387        m_loaded
.Append(name
.GetData(), lib
); 
 394 wxObject 
*wxLibraries::CreateObject(const wxString
& path
) 
 396     wxNode 
*node 
= m_loaded
.First(); 
 400         obj 
= ((wxLibrary 
*)node
->Data())->CreateObject(path
); 
 409 #endif // wxUSE_DYNLIB_CLASS