]>
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 last object we registered, it's just
83 // the new head of the wxClassInfo list:
84 m_ourLast
= wxClassInfo::GetFirst();
86 // But to find the first wxClassInfo created by this library we need to
87 // iterate until we get to the previous head as we don't have the links in
88 // the backwards direction:
89 if ( m_ourLast
!= oldFirst
)
91 for ( const wxClassInfo
* info
= m_ourLast
; ; info
= info
->GetNext() )
93 if ( info
->GetNext() == oldFirst
)
100 else // We didn't register any classes at all.
113 // Flag us for deletion
118 wxPluginLibrary::~wxPluginLibrary()
127 wxPluginLibrary
*wxPluginLibrary::RefLib()
129 wxCHECK_MSG( m_linkcount
> 0, NULL
,
130 wxT("Library had been already deleted!") );
136 bool wxPluginLibrary::UnrefLib()
138 wxASSERT_MSG( m_objcount
== 0,
139 wxT("Library unloaded before all objects were destroyed") );
141 if ( m_linkcount
== 0 || --m_linkcount
== 0 )
150 // ------------------------
152 // ------------------------
154 void wxPluginLibrary::UpdateClasses()
159 for ( const wxClassInfo
*info
= m_ourFirst
; ; info
= info
->GetNext() )
161 if( info
->GetClassName() )
163 // Hash all the class names into a local table too so
164 // we can quickly find the entry they correspond to.
165 (*ms_classes
)[info
->GetClassName()] = this;
168 if ( info
== m_ourLast
)
173 void wxPluginLibrary::RestoreClasses()
175 // Check if there is a need to restore classes.
182 for ( const wxClassInfo
*info
= m_ourFirst
; ; info
= info
->GetNext() )
184 ms_classes
->erase(ms_classes
->find(info
->GetClassName()));
186 if ( info
== m_ourLast
)
191 void wxPluginLibrary::RegisterModules()
193 // Plugin libraries might have wxModules, Register and initialise them if
196 // Note that these classes are NOT included in the reference counting since
197 // it's implicit that they will be unloaded if and when the last handle to
198 // the library is. We do have to keep a copy of the module's pointer
199 // though, as there is currently no way to Unregister it without it.
201 wxASSERT_MSG( m_linkcount
== 1,
202 wxT("RegisterModules should only be called for the first load") );
206 for ( const wxClassInfo
*info
= m_ourFirst
; ; info
= info
->GetNext() )
208 if( info
->IsKindOf(wxCLASSINFO(wxModule
)) )
210 wxModule
*m
= wxDynamicCast(info
->CreateObject(), wxModule
);
212 wxASSERT_MSG( m
, wxT("wxDynamicCast of wxModule failed") );
214 m_wxmodules
.push_back(m
);
215 wxModule::RegisterModule(m
);
218 if ( info
== m_ourLast
)
223 // FIXME: Likewise this is (well was) very similar to InitializeModules()
225 for ( wxModuleList::iterator it
= m_wxmodules
.begin();
226 it
!= m_wxmodules
.end();
231 wxLogDebug(wxT("wxModule::Init() failed for wxPluginLibrary"));
233 // XXX: Watch this, a different hash implementation might break it,
234 // a good hash implementation would let us fix it though.
236 // The name of the game is to remove any uninitialised modules and
237 // let the dtor Exit the rest on shutdown, (which we'll initiate
240 wxModuleList::iterator oldNode
= m_wxmodules
.end();
243 if( oldNode
!= m_wxmodules
.end() )
244 m_wxmodules
.erase(oldNode
);
245 wxModule::UnregisterModule( *it
);
247 } while( it
!= m_wxmodules
.end() );
249 --m_linkcount
; // Flag us for deletion
255 void wxPluginLibrary::UnregisterModules()
257 wxModuleList::iterator it
;
259 for ( it
= m_wxmodules
.begin(); it
!= m_wxmodules
.end(); ++it
)
262 for ( it
= m_wxmodules
.begin(); it
!= m_wxmodules
.end(); ++it
)
263 wxModule::UnregisterModule( *it
);
265 // NB: content of the list was deleted by UnregisterModule calls above:
270 // ---------------------------------------------------------------------------
272 // ---------------------------------------------------------------------------
274 wxDLManifest
* wxPluginManager::ms_manifest
= NULL
;
276 // ------------------------
278 // ------------------------
281 wxPluginManager::LoadLibrary(const wxString
&libname
, int flags
)
283 wxString
realname(libname
);
285 if( !(flags
& wxDL_VERBATIM
) )
286 realname
+= wxDynamicLibrary::GetDllExt();
288 wxPluginLibrary
*entry
;
290 if ( flags
& wxDL_NOSHARE
)
296 entry
= FindByName(realname
);
301 wxLogTrace(wxT("dll"),
302 wxT("LoadLibrary(%s): already loaded."), realname
.c_str());
308 entry
= new wxPluginLibrary( libname
, flags
);
310 if ( entry
->IsLoaded() )
312 (*ms_manifest
)[realname
] = entry
;
314 wxLogTrace(wxT("dll"),
315 wxT("LoadLibrary(%s): loaded ok."), realname
.c_str());
320 wxLogTrace(wxT("dll"),
321 wxT("LoadLibrary(%s): failed to load."), realname
.c_str());
323 // we have created entry just above
324 if ( !entry
->UnrefLib() )
326 // ... so UnrefLib() is supposed to delete it
327 wxFAIL_MSG( wxT("Currently linked library is not loaded?") );
337 bool wxPluginManager::UnloadLibrary(const wxString
& libname
)
339 wxString realname
= libname
;
341 wxPluginLibrary
*entry
= FindByName(realname
);
345 realname
+= wxDynamicLibrary::GetDllExt();
347 entry
= FindByName(realname
);
352 wxLogDebug(wxT("Attempt to unload library '%s' which is not loaded."),
358 wxLogTrace(wxT("dll"), wxT("UnloadLibrary(%s)"), realname
.c_str());
360 if ( !entry
->UnrefLib() )
362 // not really unloaded yet
366 ms_manifest
->erase(ms_manifest
->find(realname
));
371 // ------------------------
372 // Class implementation
373 // ------------------------
375 bool wxPluginManager::Load(const wxString
&libname
, int flags
)
377 m_entry
= wxPluginManager::LoadLibrary(libname
, flags
);
382 void wxPluginManager::Unload()
384 wxCHECK_RET( m_entry
, wxT("unloading an invalid wxPluginManager?") );
386 for ( wxDLManifest::iterator i
= ms_manifest
->begin();
387 i
!= ms_manifest
->end();
390 if ( i
->second
== m_entry
)
392 ms_manifest
->erase(i
);
402 #endif // wxUSE_DYNAMIC_LOADER