1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:      Dynamic loading framework 
   4 // Author:       Ron Lee, David Falkinder, Vadim Zeitlin and a cast of 1000's 
   5 //               (derived in part from dynlib.cpp (c) 1998 Guilhem Lavaux) 
   9 // Copyright:    (c) 2001 Ron Lee <ron@debian.org> 
  10 // Licence:      wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  14 #pragma implementation "dynload.h" 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  21 #include "wx/wxprec.h" 
  27 #if wxUSE_DYNAMIC_LOADER 
  30     #include "wx/msw/private.h" 
  40 #include "wx/strconv.h" 
  42 #include "wx/dynload.h" 
  43 #include "wx/module.h" 
  46 // --------------------------------------------------------------------------- 
  48 // --------------------------------------------------------------------------- 
  51 wxDLImports
*  wxPluginLibrary::ms_classes 
= NULL
; 
  53 class wxPluginLibraryModule 
: public wxModule
 
  56     wxPluginLibraryModule() { } 
  58     // TODO: create ms_classes on demand, why always preallocate it? 
  61         wxPluginLibrary::ms_classes 
= new wxDLImports
; 
  62         wxPluginManager::CreateManifest(); 
  68         delete wxPluginLibrary::ms_classes
; 
  69         wxPluginLibrary::ms_classes 
= NULL
; 
  70         wxPluginManager::ClearManifest(); 
  74     DECLARE_DYNAMIC_CLASS(wxPluginLibraryModule 
) 
  77 IMPLEMENT_DYNAMIC_CLASS(wxPluginLibraryModule
, wxModule
) 
  80 wxPluginLibrary::wxPluginLibrary(const wxString 
&libname
, int flags
) 
  84     m_before 
= wxClassInfo::sm_first
; 
  85     Load( libname
, flags 
); 
  86     m_after 
= wxClassInfo::sm_first
; 
  95         // Flag us for deletion 
 100 wxPluginLibrary::~wxPluginLibrary() 
 109 wxPluginLibrary 
*wxPluginLibrary::RefLib() 
 111     wxCHECK_MSG( m_linkcount 
> 0, NULL
, 
 112                  _T("Library had been already deleted!") ); 
 118 bool wxPluginLibrary::UnrefLib() 
 120     wxASSERT_MSG( m_objcount 
== 0, 
 121                   _T("Library unloaded before all objects were destroyed") ); 
 123     if ( m_linkcount 
== 0 || --m_linkcount 
== 0 ) 
 132 // ------------------------ 
 134 // ------------------------ 
 136 void wxPluginLibrary::UpdateClasses() 
 138     for (wxClassInfo 
*info 
= m_after
; info 
!= m_before
; info 
= info
->m_next
) 
 140         if( info
->GetClassName() ) 
 142             // Hash all the class names into a local table too so 
 143             // we can quickly find the entry they correspond to. 
 144             (*ms_classes
)[info
->GetClassName()] = this; 
 149 void wxPluginLibrary::RestoreClasses() 
 151     // Check if there is a need to restore classes. 
 155     for(wxClassInfo 
*info 
= m_after
; info 
!= m_before
; info 
= info
->m_next
) 
 157         ms_classes
->erase(ms_classes
->find(info
->GetClassName())); 
 161 void wxPluginLibrary::RegisterModules() 
 163     // Plugin libraries might have wxModules, Register and initialise them if 
 166     // Note that these classes are NOT included in the reference counting since 
 167     // it's implicit that they will be unloaded if and when the last handle to 
 168     // the library is.  We do have to keep a copy of the module's pointer 
 169     // though, as there is currently no way to Unregister it without it. 
 171     wxASSERT_MSG( m_linkcount 
== 1, 
 172                   _T("RegisterModules should only be called for the first load") ); 
 174     for ( wxClassInfo 
*info 
= m_after
; info 
!= m_before
; info 
= info
->m_next
) 
 176         if( info
->IsKindOf(CLASSINFO(wxModule
)) ) 
 178             wxModule 
*m 
= wxDynamicCast(info
->CreateObject(), wxModule
); 
 180             wxASSERT_MSG( m
, _T("wxDynamicCast of wxModule failed") ); 
 182             m_wxmodules
.push_back(m
); 
 183             wxModule::RegisterModule(m
); 
 187     // FIXME: Likewise this is (well was) very similar to InitializeModules() 
 189     for ( wxModuleList::iterator it 
= m_wxmodules
.begin(); 
 190           it 
!= m_wxmodules
.end(); 
 195             wxLogDebug(_T("wxModule::Init() failed for wxPluginLibrary")); 
 197             // XXX: Watch this, a different hash implementation might break it, 
 198             //      a good hash implementation would let us fix it though. 
 200             // The name of the game is to remove any uninitialised modules and 
 201             // let the dtor Exit the rest on shutdown, (which we'll initiate 
 204             wxModuleList::iterator oldNode 
= m_wxmodules
.end(); 
 207                 if( oldNode 
!= m_wxmodules
.end() ) 
 208                     m_wxmodules
.erase(oldNode
); 
 209                 wxModule::UnregisterModule( *it 
); 
 211             } while( it 
!= m_wxmodules
.end() ); 
 213             --m_linkcount
;     // Flag us for deletion 
 219 void wxPluginLibrary::UnregisterModules() 
 221     wxModuleList::iterator it
; 
 223     for ( it 
= m_wxmodules
.begin(); it 
!= m_wxmodules
.end(); ++it 
) 
 226     for ( it 
= m_wxmodules
.begin(); it 
!= m_wxmodules
.end(); ++it 
) 
 227         wxModule::UnregisterModule( *it 
); 
 229     // NB: content of the list was deleted by UnregisterModule calls above: 
 234 // --------------------------------------------------------------------------- 
 236 // --------------------------------------------------------------------------- 
 238 wxDLManifest
*   wxPluginManager::ms_manifest 
= NULL
; 
 240 // ------------------------ 
 242 // ------------------------ 
 245 wxPluginManager::LoadLibrary(const wxString 
&libname
, int flags
) 
 247     wxString 
realname(libname
); 
 249     if( !(flags 
& wxDL_VERBATIM
) ) 
 250         realname 
+= wxDynamicLibrary::GetDllExt(); 
 252     wxPluginLibrary 
*entry
; 
 254     if ( flags 
& wxDL_NOSHARE 
) 
 260         entry 
= FindByName(realname
); 
 265         wxLogTrace(_T("dll"), 
 266                    _T("LoadLibrary(%s): already loaded."), realname
.c_str()); 
 272         entry 
= new wxPluginLibrary( libname
, flags 
); 
 274         if ( entry
->IsLoaded() ) 
 276             (*ms_manifest
)[realname
] = entry
; 
 278             wxLogTrace(_T("dll"), 
 279                        _T("LoadLibrary(%s): loaded ok."), realname
.c_str()); 
 284             wxLogTrace(_T("dll"), 
 285                        _T("LoadLibrary(%s): failed to load."), realname
.c_str()); 
 287             // we have created entry just above 
 288             if ( !entry
->UnrefLib() ) 
 290                 // ... so UnrefLib() is supposed to delete it 
 291                 wxFAIL_MSG( _T("Currently linked library is not loaded?") ); 
 301 bool wxPluginManager::UnloadLibrary(const wxString
& libname
) 
 303     wxString realname 
= libname
; 
 305     wxPluginLibrary 
*entry 
= FindByName(realname
); 
 309         realname 
+= wxDynamicLibrary::GetDllExt(); 
 311         entry 
= FindByName(realname
); 
 316         wxLogDebug(_T("Attempt to unload library '%s' which is not loaded."), 
 322     wxLogTrace(_T("dll"), _T("UnloadLibrary(%s)"), realname
.c_str()); 
 324     if ( !entry
->UnrefLib() ) 
 326         // not really unloaded yet 
 330     ms_manifest
->erase(ms_manifest
->find(realname
)); 
 335 // ------------------------ 
 336 // Class implementation 
 337 // ------------------------ 
 339 bool wxPluginManager::Load(const wxString 
&libname
, int flags
) 
 341     m_entry 
= wxPluginManager::LoadLibrary(libname
, flags
); 
 346 void wxPluginManager::Unload() 
 348     wxCHECK_RET( m_entry
, _T("unloading an invalid wxPluginManager?") ); 
 350     for ( wxDLManifest::iterator i 
= ms_manifest
->begin(); 
 351           i 
!= ms_manifest
->end(); 
 354         if ( i
->second 
== m_entry 
) 
 356             ms_manifest
->erase(i
); 
 368 #if WXWIN_COMPATIBILITY_2_2 
 370 wxPluginLibrary 
*wxPluginManager::GetObjectFromHandle(wxDllType handle
) 
 372     for ( wxDLManifest::iterator i 
= ms_manifest
->begin(); 
 373           i 
!= ms_manifest
->end(); 
 376         wxPluginLibrary 
* const lib 
= i
->second
; 
 378         if ( lib
->GetLibHandle() == handle 
) 
 385 // --------------------------------------------------------------------------- 
 386 // wxDllLoader   (all these methods are static) 
 387 // --------------------------------------------------------------------------- 
 390 wxDllType 
wxDllLoader::LoadLibrary(const wxString 
&name
, bool *success
) 
 392     wxPluginLibrary 
*p 
= wxPluginManager::LoadLibrary
 
 395                             wxDL_DEFAULT 
| wxDL_VERBATIM 
| wxDL_NOSHARE
 
 399         *success 
= p 
!= NULL
; 
 401     return p 
? p
->GetLibHandle() : 0; 
 404 void wxDllLoader::UnloadLibrary(wxDllType handle
) 
 406     wxPluginLibrary 
*p 
= wxPluginManager::GetObjectFromHandle(handle
); 
 408     wxCHECK_RET( p
, _T("Unloading a library not loaded with wxDllLoader?") ); 
 414 wxDllLoader::GetSymbol(wxDllType dllHandle
, const wxString 
&name
, bool *success
) 
 416     wxPluginLibrary 
*p 
= wxPluginManager::GetObjectFromHandle(dllHandle
); 
 420         wxFAIL_MSG( _T("Using a library not loaded with wxDllLoader?") ); 
 428     return p
->GetSymbol(name
, success
); 
 432 // --------------------------------------------------------------------------- 
 434 // --------------------------------------------------------------------------- 
 436 wxLibraries wxTheLibraries
; 
 438 // ============================================================================ 
 440 // ============================================================================ 
 442 // construct the full name from the base shared object name: adds a .dll 
 443 // suffix under Windows or .so under Unix 
 444 static wxString 
ConstructLibraryName(const wxString
& basename
) 
 447     fullname 
<< basename 
<< wxDllLoader::GetDllExt(); 
 452 // --------------------------------------------------------------------------- 
 453 // wxLibrary (one instance per dynamic library) 
 454 // --------------------------------------------------------------------------- 
 456 wxLibrary::wxLibrary(wxDllType handle
) 
 458     typedef wxClassInfo 
*(*t_get_first
)(void); 
 459     t_get_first get_first
; 
 463     // Some system may use a local heap for library. 
 464     get_first 
= (t_get_first
)GetSymbol(_T("wxGetClassFirst")); 
 465     // It is a wxWidgets DLL. 
 467         PrepareClasses(get_first()); 
 470 wxLibrary::~wxLibrary() 
 474         wxDllLoader::UnloadLibrary(m_handle
); 
 478 wxObject 
*wxLibrary::CreateObject(const wxString
& name
) 
 480     wxClassInfo 
*info 
= (wxClassInfo 
*)classTable
.Get(name
); 
 485     return info
->CreateObject(); 
 488 void wxLibrary::PrepareClasses(wxClassInfo 
*first
) 
 490     // Index all class infos by their class name 
 491     wxClassInfo 
*info 
= first
; 
 494         if (info
->m_className
) 
 495             classTable
.Put(info
->m_className
, (wxObject 
*)info
); 
 499 #if !wxUSE_EXTENDED_RTTI 
 500     // Set base pointers for each wxClassInfo 
 504         if (info
->GetBaseClassName1()) 
 505             info
->m_baseInfo1 
= (wxClassInfo 
*)classTable
.Get(info
->GetBaseClassName1()); 
 506         if (info
->GetBaseClassName2()) 
 507             info
->m_baseInfo2 
= (wxClassInfo 
*)classTable
.Get(info
->GetBaseClassName2()); 
 513 void *wxLibrary::GetSymbol(const wxString
& symbname
) 
 515    return wxDllLoader::GetSymbol(m_handle
, symbname
); 
 519 // --------------------------------------------------------------------------- 
 520 // wxLibraries (only one instance should normally exist) 
 521 // --------------------------------------------------------------------------- 
 523 wxLibraries::wxLibraries():m_loaded(wxKEY_STRING
) 
 527 wxLibraries::~wxLibraries() 
 529     wxNode 
*node 
= m_loaded
.GetFirst(); 
 532         wxLibrary 
*lib 
= (wxLibrary 
*)node
->GetData(); 
 535         node 
= node
->GetNext(); 
 539 wxLibrary 
*wxLibraries::LoadLibrary(const wxString
& name
) 
 542     wxClassInfo 
*old_sm_first
; 
 543     wxNode      
*node 
= m_loaded
.Find(name
.GetData()); 
 546         return ((wxLibrary 
*)node
->GetData()); 
 548     // If DLL shares data, this is necessary. 
 549     old_sm_first 
= wxClassInfo::sm_first
; 
 550     wxClassInfo::sm_first 
= NULL
; 
 552     wxString libname 
= ConstructLibraryName(name
); 
 554     bool success 
= false; 
 555     wxDllType handle 
= wxDllLoader::LoadLibrary(libname
, &success
); 
 558        lib 
= new wxLibrary(handle
); 
 559        wxClassInfo::sm_first 
= old_sm_first
; 
 561        m_loaded
.Append(name
.GetData(), lib
); 
 568 wxObject 
*wxLibraries::CreateObject(const wxString
& path
) 
 570     wxNode 
*node 
= m_loaded
.GetFirst(); 
 574         obj 
= ((wxLibrary 
*)node
->GetData())->CreateObject(path
); 
 578         node 
= node
->GetNext(); 
 583 #endif  // WXWIN_COMPATIBILITY_2_2 
 586 #endif  // wxUSE_DYNAMIC_LOADER