7ed9cd2891
wxPluginLibrary objects had to be unloaded in exactly the reverse order to which they were loaded in. This was not documented and was a serious limitation for any realistic use of plugins anyhow, so fix it and allow unloading them in any order now. Instead of keeping a pointer to the last wxClassInfo not created by this plugin, now keep a pointer to the first wxClassInfo that was created by it. This makes the code slightly more complex but this pointer, unlike the old one, remains valid even if another plugin was unloaded. Closes #14261. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@71571 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
157 lines
5.3 KiB
C++
157 lines
5.3 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: wx/dynload.h
|
|
// Purpose: Dynamic loading framework
|
|
// Author: Ron Lee, David Falkinder, Vadim Zeitlin and a cast of 1000's
|
|
// (derived in part from dynlib.cpp (c) 1998 Guilhem Lavaux)
|
|
// Modified by:
|
|
// Created: 03/12/01
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 2001 Ron Lee <ron@debian.org>
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef _WX_DYNAMICLOADER_H__
|
|
#define _WX_DYNAMICLOADER_H__
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "wx/defs.h"
|
|
|
|
#if wxUSE_DYNAMIC_LOADER
|
|
|
|
#include "wx/dynlib.h"
|
|
#include "wx/hashmap.h"
|
|
#include "wx/module.h"
|
|
|
|
class WXDLLIMPEXP_FWD_BASE wxPluginLibrary;
|
|
|
|
|
|
WX_DECLARE_STRING_HASH_MAP_WITH_DECL(wxPluginLibrary *, wxDLManifest,
|
|
class WXDLLIMPEXP_BASE);
|
|
typedef wxDLManifest wxDLImports;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// wxPluginLibrary
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// NOTE: Do not attempt to use a base class pointer to this class.
|
|
// wxDL is not virtual and we deliberately hide some of it's
|
|
// methods here.
|
|
//
|
|
// Unless you know exacty why you need to, you probably shouldn't
|
|
// instantiate this class directly anyway, use wxPluginManager
|
|
// instead.
|
|
|
|
class WXDLLIMPEXP_BASE wxPluginLibrary : public wxDynamicLibrary
|
|
{
|
|
public:
|
|
|
|
static wxDLImports* ms_classes; // Static hash of all imported classes.
|
|
|
|
wxPluginLibrary( const wxString &libname, int flags = wxDL_DEFAULT );
|
|
~wxPluginLibrary();
|
|
|
|
wxPluginLibrary *RefLib();
|
|
bool UnrefLib();
|
|
|
|
// These two are called by the PluginSentinel on (PLUGGABLE) object
|
|
// creation/destruction. There is usually no reason for the user to
|
|
// call them directly. We have to separate this from the link count,
|
|
// since the two are not interchangeable.
|
|
|
|
// FIXME: for even better debugging PluginSentinel should register
|
|
// the name of the class created too, then we can state
|
|
// exactly which object was not destroyed which may be
|
|
// difficult to find otherwise. Also this code should
|
|
// probably only be active in DEBUG mode, but let's just
|
|
// get it right first.
|
|
|
|
void RefObj() { ++m_objcount; }
|
|
void UnrefObj()
|
|
{
|
|
wxASSERT_MSG( m_objcount > 0, wxT("Too many objects deleted??") );
|
|
--m_objcount;
|
|
}
|
|
|
|
// Override/hide some base class methods
|
|
|
|
bool IsLoaded() const { return m_linkcount > 0; }
|
|
void Unload() { UnrefLib(); }
|
|
|
|
private:
|
|
|
|
// These pointers may be NULL but if they are not, then m_ourLast follows
|
|
// m_ourFirst in the linked list, i.e. can be found by calling GetNext() a
|
|
// sufficient number of times.
|
|
const wxClassInfo *m_ourFirst; // first class info in this plugin
|
|
const wxClassInfo *m_ourLast; // ..and the last one
|
|
|
|
size_t m_linkcount; // Ref count of library link calls
|
|
size_t m_objcount; // ..and (pluggable) object instantiations.
|
|
wxModuleList m_wxmodules; // any wxModules that we initialised.
|
|
|
|
void UpdateClasses(); // Update ms_classes
|
|
void RestoreClasses(); // Removes this library from ms_classes
|
|
void RegisterModules(); // Init any wxModules in the lib.
|
|
void UnregisterModules(); // Cleanup any wxModules we installed.
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxPluginLibrary);
|
|
};
|
|
|
|
|
|
class WXDLLIMPEXP_BASE wxPluginManager
|
|
{
|
|
public:
|
|
|
|
// Static accessors.
|
|
|
|
static wxPluginLibrary *LoadLibrary( const wxString &libname,
|
|
int flags = wxDL_DEFAULT );
|
|
static bool UnloadLibrary(const wxString &libname);
|
|
|
|
// Instance methods.
|
|
|
|
wxPluginManager() : m_entry(NULL) {}
|
|
wxPluginManager(const wxString &libname, int flags = wxDL_DEFAULT)
|
|
{
|
|
Load(libname, flags);
|
|
}
|
|
~wxPluginManager() { if ( IsLoaded() ) Unload(); }
|
|
|
|
bool Load(const wxString &libname, int flags = wxDL_DEFAULT);
|
|
void Unload();
|
|
|
|
bool IsLoaded() const { return m_entry && m_entry->IsLoaded(); }
|
|
void *GetSymbol(const wxString &symbol, bool *success = 0)
|
|
{
|
|
return m_entry->GetSymbol( symbol, success );
|
|
}
|
|
|
|
static void CreateManifest() { ms_manifest = new wxDLManifest(wxKEY_STRING); }
|
|
static void ClearManifest() { delete ms_manifest; ms_manifest = NULL; }
|
|
|
|
private:
|
|
// return the pointer to the entry for the library with given name in
|
|
// ms_manifest or NULL if none
|
|
static wxPluginLibrary *FindByName(const wxString& name)
|
|
{
|
|
const wxDLManifest::iterator i = ms_manifest->find(name);
|
|
|
|
return i == ms_manifest->end() ? NULL : i->second;
|
|
}
|
|
|
|
static wxDLManifest* ms_manifest; // Static hash of loaded libs.
|
|
wxPluginLibrary* m_entry; // Cache our entry in the manifest.
|
|
|
|
// We could allow this class to be copied if we really
|
|
// wanted to, but not without modification.
|
|
wxDECLARE_NO_COPY_CLASS(wxPluginManager);
|
|
};
|
|
|
|
|
|
#endif // wxUSE_DYNAMIC_LOADER
|
|
#endif // _WX_DYNAMICLOADER_H__
|
|
|