]>
git.saurik.com Git - wxWidgets.git/blob - src/common/dynload.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/dynload.cpp
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 // ----------------------------------------------------------------------------
15 // ----------------------------------------------------------------------------
17 #include "wx/wxprec.h"
23 #if wxUSE_DYNAMIC_LOADER
26 #include "wx/msw/private.h"
34 #include "wx/module.h"
37 #include "wx/strconv.h"
39 #include "wx/dynload.h"
42 // ---------------------------------------------------------------------------
44 // ---------------------------------------------------------------------------
47 wxDLImports
* wxPluginLibrary::ms_classes
= NULL
;
49 class wxPluginLibraryModule
: public wxModule
52 wxPluginLibraryModule() { }
54 // TODO: create ms_classes on demand, why always preallocate it?
57 wxPluginLibrary::ms_classes
= new wxDLImports
;
58 wxPluginManager::CreateManifest();
64 wxDELETE(wxPluginLibrary::ms_classes
);
65 wxPluginManager::ClearManifest();
69 DECLARE_DYNAMIC_CLASS(wxPluginLibraryModule
)
72 IMPLEMENT_DYNAMIC_CLASS(wxPluginLibraryModule
, wxModule
)
75 wxPluginLibrary::wxPluginLibrary(const wxString
&libname
, int flags
)
79 const wxClassInfo
* const oldFirst
= wxClassInfo::GetFirst();
80 Load( libname
, flags
);
82 // It is simple to know what is the first object in the linked list of
83 // wxClassInfo that we registered (it's also the last one chronologically),
84 // it's just the new head of the wxClassInfo list:
85 m_ourFirst
= wxClassInfo::GetFirst();
87 // But to find the first wxClassInfo created by this library we need to
88 // iterate until we get to the previous head as we don't have the links in
89 // the backwards direction:
90 if ( m_ourFirst
!= oldFirst
)
92 for ( const wxClassInfo
* info
= m_ourFirst
; ; info
= info
->GetNext() )
94 if ( info
->GetNext() == oldFirst
)
101 else // We didn't register any classes at all.
114 // Flag us for deletion
119 wxPluginLibrary::~wxPluginLibrary()
128 wxPluginLibrary
*wxPluginLibrary::RefLib()
130 wxCHECK_MSG( m_linkcount
> 0, NULL
,
131 wxT("Library had been already deleted!") );
137 bool wxPluginLibrary::UnrefLib()
139 wxASSERT_MSG( m_objcount
== 0,
140 wxT("Library unloaded before all objects were destroyed") );
142 if ( m_linkcount
== 0 || --m_linkcount
== 0 )
151 // ------------------------
153 // ------------------------
155 void wxPluginLibrary::UpdateClasses()
160 for ( const wxClassInfo
*info
= m_ourFirst
; ; info
= info
->GetNext() )
162 if( info
->GetClassName() )
164 // Hash all the class names into a local table too so
165 // we can quickly find the entry they correspond to.
166 (*ms_classes
)[info
->GetClassName()] = this;
169 if ( info
== m_ourLast
)
174 void wxPluginLibrary::RestoreClasses()
176 // Check if there is a need to restore classes.
183 for ( const wxClassInfo
*info
= m_ourFirst
; ; info
= info
->GetNext() )
185 ms_classes
->erase(ms_classes
->find(info
->GetClassName()));
187 if ( info
== m_ourLast
)
192 void wxPluginLibrary::RegisterModules()
194 // Plugin libraries might have wxModules, Register and initialise them if
197 // Note that these classes are NOT included in the reference counting since
198 // it's implicit that they will be unloaded if and when the last handle to
199 // the library is. We do have to keep a copy of the module's pointer
200 // though, as there is currently no way to Unregister it without it.
202 wxASSERT_MSG( m_linkcount
== 1,
203 wxT("RegisterModules should only be called for the first load") );
207 for ( const wxClassInfo
*info
= m_ourFirst
; ; info
= info
->GetNext() )
209 if( info
->IsKindOf(wxCLASSINFO(wxModule
)) )
211 wxModule
*m
= wxDynamicCast(info
->CreateObject(), wxModule
);
213 wxASSERT_MSG( m
, wxT("wxDynamicCast of wxModule failed") );
215 m_wxmodules
.push_back(m
);
216 wxModule::RegisterModule(m
);
219 if ( info
== m_ourLast
)
224 // FIXME: Likewise this is (well was) very similar to InitializeModules()
226 for ( wxModuleList::iterator it
= m_wxmodules
.begin();
227 it
!= m_wxmodules
.end();
232 wxLogDebug(wxT("wxModule::Init() failed for wxPluginLibrary"));
234 // XXX: Watch this, a different hash implementation might break it,
235 // a good hash implementation would let us fix it though.
237 // The name of the game is to remove any uninitialised modules and
238 // let the dtor Exit the rest on shutdown, (which we'll initiate
241 wxModuleList::iterator oldNode
= m_wxmodules
.end();
244 if( oldNode
!= m_wxmodules
.end() )
245 m_wxmodules
.erase(oldNode
);
246 wxModule::UnregisterModule( *it
);
248 } while( it
!= m_wxmodules
.end() );
250 --m_linkcount
; // Flag us for deletion
256 void wxPluginLibrary::UnregisterModules()
258 wxModuleList::iterator it
;
260 for ( it
= m_wxmodules
.begin(); it
!= m_wxmodules
.end(); ++it
)
263 for ( it
= m_wxmodules
.begin(); it
!= m_wxmodules
.end(); ++it
)
264 wxModule::UnregisterModule( *it
);
266 // NB: content of the list was deleted by UnregisterModule calls above:
271 // ---------------------------------------------------------------------------
273 // ---------------------------------------------------------------------------
275 wxDLManifest
* wxPluginManager::ms_manifest
= NULL
;
277 // ------------------------
279 // ------------------------
282 wxPluginManager::LoadLibrary(const wxString
&libname
, int flags
)
284 wxString
realname(libname
);
286 if( !(flags
& wxDL_VERBATIM
) )
287 realname
+= wxDynamicLibrary::GetDllExt();
289 wxPluginLibrary
*entry
;
291 if ( flags
& wxDL_NOSHARE
)
297 entry
= FindByName(realname
);
302 wxLogTrace(wxT("dll"),
303 wxT("LoadLibrary(%s): already loaded."), realname
.c_str());
309 entry
= new wxPluginLibrary( libname
, flags
);
311 if ( entry
->IsLoaded() )
313 (*ms_manifest
)[realname
] = entry
;
315 wxLogTrace(wxT("dll"),
316 wxT("LoadLibrary(%s): loaded ok."), realname
.c_str());
321 wxLogTrace(wxT("dll"),
322 wxT("LoadLibrary(%s): failed to load."), realname
.c_str());
324 // we have created entry just above
325 if ( !entry
->UnrefLib() )
327 // ... so UnrefLib() is supposed to delete it
328 wxFAIL_MSG( wxT("Currently linked library is not loaded?") );
338 bool wxPluginManager::UnloadLibrary(const wxString
& libname
)
340 wxString realname
= libname
;
342 wxPluginLibrary
*entry
= FindByName(realname
);
346 realname
+= wxDynamicLibrary::GetDllExt();
348 entry
= FindByName(realname
);
353 wxLogDebug(wxT("Attempt to unload library '%s' which is not loaded."),
359 wxLogTrace(wxT("dll"), wxT("UnloadLibrary(%s)"), realname
.c_str());
361 if ( !entry
->UnrefLib() )
363 // not really unloaded yet
367 ms_manifest
->erase(ms_manifest
->find(realname
));
372 // ------------------------
373 // Class implementation
374 // ------------------------
376 bool wxPluginManager::Load(const wxString
&libname
, int flags
)
378 m_entry
= wxPluginManager::LoadLibrary(libname
, flags
);
383 void wxPluginManager::Unload()
385 wxCHECK_RET( m_entry
, wxT("unloading an invalid wxPluginManager?") );
387 for ( wxDLManifest::iterator i
= ms_manifest
->begin();
388 i
!= ms_manifest
->end();
391 if ( i
->second
== m_entry
)
393 ms_manifest
->erase(i
);
403 #endif // wxUSE_DYNAMIC_LOADER