+
+// ---------------------------------------------------------------------------
+// Global variables
+// ---------------------------------------------------------------------------
+
+wxLibraries wxTheLibraries;
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// construct the full name from the base shared object name: adds a .dll
+// suffix under Windows or .so under Unix
+static wxString ConstructLibraryName(const wxString& basename)
+{
+ wxString fullname;
+ fullname << basename << wxDllLoader::GetDllExt();
+
+ return fullname;
+}
+
+// ---------------------------------------------------------------------------
+// wxLibrary (one instance per dynamic library)
+// ---------------------------------------------------------------------------
+
+wxLibrary::wxLibrary(wxDllType handle)
+{
+ typedef wxClassInfo *(*t_get_first)(void);
+ t_get_first get_first;
+
+ m_handle = handle;
+
+ // Some system may use a local heap for library.
+ get_first = (t_get_first)GetSymbol(_T("wxGetClassFirst"));
+ // It is a wxWidgets DLL.
+ if (get_first)
+ PrepareClasses(get_first());
+}
+
+wxLibrary::~wxLibrary()
+{
+ if ( m_handle )
+ {
+ wxDllLoader::UnloadLibrary(m_handle);
+ }
+}
+
+wxObject *wxLibrary::CreateObject(const wxString& name)
+{
+ wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
+
+ if (!info)
+ return NULL;
+
+ return info->CreateObject();
+}
+
+void wxLibrary::PrepareClasses(wxClassInfo *first)
+{
+ // Index all class infos by their class name
+ wxClassInfo *info = first;
+ while (info)
+ {
+ if (info->m_className)
+ classTable.Put(info->m_className, (wxObject *)info);
+ info = info->m_next;
+ }
+
+#if !wxUSE_EXTENDED_RTTI
+ // Set base pointers for each wxClassInfo
+ info = first;
+ while (info)
+ {
+ if (info->GetBaseClassName1())
+ info->m_baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
+ if (info->GetBaseClassName2())
+ info->m_baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
+ info = info->m_next;
+ }
+#endif
+}
+
+void *wxLibrary::GetSymbol(const wxString& symbname)
+{
+ return wxDllLoader::GetSymbol(m_handle, symbname);
+}
+
+
+// ---------------------------------------------------------------------------
+// wxLibraries (only one instance should normally exist)
+// ---------------------------------------------------------------------------
+
+wxLibraries::wxLibraries():m_loaded(wxKEY_STRING)
+{
+}
+
+wxLibraries::~wxLibraries()
+{
+ wxNode *node = m_loaded.First();
+
+ while (node) {
+ wxLibrary *lib = (wxLibrary *)node->Data();
+ delete lib;
+
+ node = node->Next();
+ }
+}
+
+wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
+{
+ wxLibrary *lib;
+ wxClassInfo *old_sm_first;
+ wxNode *node = m_loaded.Find(name.GetData());
+
+ if (node != NULL)
+ return ((wxLibrary *)node->Data());
+
+ // If DLL shares data, this is necessary.
+ old_sm_first = wxClassInfo::sm_first;
+ wxClassInfo::sm_first = NULL;
+
+ wxString libname = ConstructLibraryName(name);
+
+ bool success = false;
+ wxDllType handle = wxDllLoader::LoadLibrary(libname, &success);
+ if(success)
+ {
+ lib = new wxLibrary(handle);
+ wxClassInfo::sm_first = old_sm_first;
+
+ m_loaded.Append(name.GetData(), lib);
+ }
+ else
+ lib = NULL;
+ return lib;
+}
+
+wxObject *wxLibraries::CreateObject(const wxString& path)
+{
+ wxNode *node = m_loaded.First();
+ wxObject *obj;
+
+ while (node) {
+ obj = ((wxLibrary *)node->Data())->CreateObject(path);
+ if (obj)
+ return obj;
+
+ node = node->Next();
+ }
+ return NULL;
+}
+