home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / dynload.cpp < prev    next >
C/C++ Source or Header  |  2002-12-22  |  20KB  |  728 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:         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)
  6. // Modified by:
  7. // Created:      03/12/01
  8. // RCS-ID:       $Id: dynload.cpp,v 1.19.2.4 2002/12/19 23:43:33 VS Exp $
  9. // Copyright:    (c) 2001 Ron Lee <ron@debian.org>
  10. // Licence:      wxWindows license
  11. /////////////////////////////////////////////////////////////////////////////
  12.  
  13. #ifdef __GNUG__
  14. #pragma implementation "dynload.h"
  15. #endif
  16.  
  17. // ----------------------------------------------------------------------------
  18. // headers
  19. // ----------------------------------------------------------------------------
  20.  
  21. #include "wx/wxprec.h"
  22.  
  23. #ifdef __BORLANDC__
  24.     #pragma hdrstop
  25. #endif
  26.  
  27. #if wxUSE_DYNAMIC_LOADER
  28.  
  29. #ifdef __WINDOWS__
  30.     #include "wx/msw/private.h"
  31. #endif
  32.  
  33. #ifndef WX_PRECOMP
  34.     #include "wx/log.h"
  35.     #include "wx/intl.h"
  36.     #include "wx/hash.h"
  37. #endif
  38.  
  39. #include "wx/filename.h"        // for SplitPath()
  40. #include "wx/strconv.h"
  41.  
  42. #include "wx/dynload.h"
  43. #include "wx/module.h"
  44.  
  45. #if defined(__DARWIN__)
  46. /* Porting notes:
  47.  *   The dlopen port is a port from dl_next.xs by Anno Siegel.
  48.  *   dl_next.xs is itself a port from dl_dlopen.xs by Paul Marquess.
  49.  *   The method used here is just to supply the sun style dlopen etc.
  50.  *   functions in terms of Darwin NS*.
  51.  */
  52. void *dlopen(const char *path, int mode /* mode is ignored */);
  53. void *dlsym(void *handle, const char *symbol);
  54. int   dlclose(void *handle);
  55. const char *dlerror(void);
  56. #endif
  57.  
  58. // ============================================================================
  59. // implementation
  60. // ============================================================================
  61.  
  62. // ---------------------------------------------------------------------------
  63. // wxDynamicLibrary
  64. // ---------------------------------------------------------------------------
  65.  
  66. //FIXME:  This class isn't really common at all, it should be moved into
  67. //        platform dependent files.
  68.  
  69. #if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
  70.     const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll");
  71. #elif defined(__UNIX__)
  72.     #if defined(__HPUX__)
  73.         const wxChar *wxDynamicLibrary::ms_dllext = _T(".sl");
  74.     #else
  75.         const wxChar *wxDynamicLibrary::ms_dllext = _T(".so");
  76.     #endif
  77. #endif
  78.  
  79. wxDllType wxDynamicLibrary::GetProgramHandle()
  80. {
  81. #if defined( HAVE_DLOPEN ) && !defined(__EMX__)
  82.    return dlopen(0, RTLD_LAZY);
  83. #elif defined (HAVE_SHL_LOAD)
  84.    return PROG_HANDLE;
  85. #else
  86.    wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
  87.    return 0;
  88. #endif
  89. }
  90.  
  91. bool wxDynamicLibrary::Load(wxString libname, int flags)
  92. {
  93.     wxASSERT_MSG(m_handle == 0, _T("Library already loaded."));
  94.  
  95.     // add the proper extension for the DLL ourselves unless told not to
  96.     if ( !(flags & wxDL_VERBATIM) )
  97.     {
  98.         // and also check that the libname doesn't already have it
  99.         wxString ext;
  100.         wxFileName::SplitPath(libname, NULL, NULL, &ext);
  101.         if ( ext.empty() )
  102.         {
  103.             libname += GetDllExt();
  104.         }
  105.     }
  106.  
  107.     // different ways to load a shared library
  108.     //
  109.     // FIXME: should go to the platform-specific files!
  110. #if defined(__WXMAC__) && !defined(__DARWIN__)
  111.     FSSpec      myFSSpec;
  112.     Ptr         myMainAddr;
  113.     Str255      myErrName;
  114.  
  115.     wxMacFilename2FSSpec( libname , &myFSSpec );
  116.  
  117.     if( GetDiskFragment( &myFSSpec,
  118.                          0,
  119.                          kCFragGoesToEOF,
  120.                          "\p",
  121.                          kPrivateCFragCopy,
  122.                          &m_handle,
  123.                          &myMainAddr,
  124.                          myErrName ) != noErr )
  125.     {
  126.         p2cstr( myErrName );
  127.         wxLogSysError( _("Failed to load shared library '%s' Error '%s'"),
  128.                        libname.c_str(),
  129.                        (char*)myErrName );
  130.         m_handle = 0;
  131.     }
  132.  
  133. #elif defined(__WXPM__) || defined(__EMX__)
  134.     char    err[256] = "";
  135.     DosLoadModule(err, sizeof(err), libname.c_str(), &m_handle);
  136.  
  137. #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
  138.  
  139. #if defined(__VMS) || defined(__DARWIN__)
  140.     m_handle = dlopen(libname.c_str(), 0);  // The second parameter is ignored
  141. #else // !__VMS  && !__DARWIN__
  142.     int rtldFlags = 0;
  143.  
  144.     if ( flags & wxDL_LAZY )
  145.     {
  146.         wxASSERT_MSG( (flags & wxDL_NOW) == 0,
  147.                       _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
  148. #ifdef RTLD_LAZY
  149.         rtldFlags |= RTLD_LAZY;
  150. #else
  151.         wxLogDebug(_T("wxDL_LAZY is not supported on this platform"));
  152. #endif
  153.     }
  154.     else if ( flags & wxDL_NOW )
  155.     {
  156. #ifdef RTLD_NOW
  157.         rtldFlags |= RTLD_NOW;
  158. #else
  159.         wxLogDebug(_T("wxDL_NOW is not supported on this platform"));
  160. #endif
  161.     }
  162.  
  163.     if ( flags & wxDL_GLOBAL )
  164.     {
  165. #ifdef RTLD_GLOBAL
  166.         rtldFlags |= RTLD_GLOBAL;
  167. #else
  168.         wxLogDebug(_T("RTLD_GLOBAL is not supported on this platform."));
  169. #endif
  170.     }
  171.  
  172.     m_handle = dlopen(libname.fn_str(), rtldFlags);
  173. #endif  // __VMS || __DARWIN__ ?
  174.  
  175. #elif defined(HAVE_SHL_LOAD)
  176.     int shlFlags = 0;
  177.  
  178.     if( flags & wxDL_LAZY )
  179.     {
  180.         wxASSERT_MSG( (flags & wxDL_NOW) == 0,
  181.                       _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
  182.         shlFlags |= BIND_DEFERRED;
  183.     }
  184.     else if( flags & wxDL_NOW )
  185.     {
  186.         shlFlags |= BIND_IMMEDIATE;
  187.     }
  188.     m_handle = shl_load(libname.fn_str(), BIND_DEFERRED, 0);
  189.  
  190. #elif defined(__WINDOWS__)
  191.     m_handle = ::LoadLibrary(libname.c_str());
  192. #else
  193.     #error  "runtime shared lib support not implemented on this platform"
  194. #endif
  195.  
  196.     if ( m_handle == 0 )
  197.     {
  198.         wxString msg(_("Failed to load shared library '%s'"));
  199. #if defined(HAVE_DLERROR) && !defined(__EMX__)
  200.  
  201. #if wxUSE_UNICODE
  202.         wxWCharBuffer buffer = wxConvLocal.cMB2WC( dlerror() );
  203.         const wxChar *err = buffer;
  204. #else
  205.         const wxChar *err = dlerror();
  206. #endif
  207.  
  208.         if( err )
  209.             wxLogError( msg, err );
  210. #else
  211.         wxLogSysError( msg, libname.c_str() );
  212. #endif
  213.     }
  214.  
  215.     return IsLoaded();
  216. }
  217.  
  218. void wxDynamicLibrary::Unload()
  219. {
  220.     if( IsLoaded() )
  221.     {
  222. #if defined(__WXPM__) || defined(__EMX__)
  223.         DosFreeModule( m_handle );
  224. #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
  225.         dlclose( m_handle );
  226. #elif defined(HAVE_SHL_LOAD)
  227.         shl_unload( m_handle );
  228. #elif defined(__WINDOWS__)
  229.         ::FreeLibrary( m_handle );
  230. #elif defined(__WXMAC__) && !defined(__DARWIN__)
  231.         CloseConnection( (CFragConnectionID*) &m_handle );
  232. #else
  233. #error  "runtime shared lib support not implemented"
  234. #endif
  235.         m_handle = 0;
  236.     }
  237. }
  238.  
  239. void *wxDynamicLibrary::GetSymbol(const wxString &name, bool *success) const
  240. {
  241.     wxCHECK_MSG( IsLoaded(), NULL,
  242.                  _T("Can't load symbol from unloaded library") );
  243.  
  244.     bool     failed = FALSE;
  245.     void    *symbol = 0;
  246.  
  247. #if defined(__WXMAC__) && !defined(__DARWIN__)
  248.     Ptr                 symAddress;
  249.     CFragSymbolClass    symClass;
  250.     Str255              symName;
  251. #if TARGET_CARBON
  252.     c2pstrcpy( (StringPtr) symName, name );
  253. #else
  254.     strcpy( (char *)symName, name );
  255.     c2pstr( (char *)symName );
  256. #endif
  257.     if( FindSymbol( dllHandle, symName, &symAddress, &symClass ) == noErr )
  258.         symbol = (void *)symAddress;
  259.  
  260. #elif defined(__WXPM__) || defined(__EMX__)
  261.     DosQueryProcAddr( m_handle, 1L, name.c_str(), (PFN*)symbol );
  262.  
  263. #elif defined(HAVE_DLOPEN) || defined(__DARWIN__)
  264.     symbol = dlsym( m_handle, name.fn_str() );
  265.  
  266. #elif defined(HAVE_SHL_LOAD)
  267.     // use local variable since shl_findsym modifies the handle argument
  268.     // to indicate where the symbol was found (GD)
  269.     wxDllType the_handle = m_handle;
  270.     if( shl_findsym( &the_handle, name.fn_str(), TYPE_UNDEFINED, &symbol ) != 0 )
  271.         symbol = 0;
  272.  
  273. #elif defined(__WINDOWS__)
  274.     symbol = (void*) ::GetProcAddress( m_handle, name.mb_str() );
  275.  
  276. #else
  277. #error  "runtime shared lib support not implemented"
  278. #endif
  279.  
  280.     if ( !symbol )
  281.     {
  282. #if defined(HAVE_DLERROR) && !defined(__EMX__)
  283.  
  284. #if wxUSE_UNICODE
  285.         wxWCharBuffer buffer = wxConvLocal.cMB2WC( dlerror() );
  286.         const wxChar *err = buffer;
  287. #else
  288.         const wxChar *err = dlerror();
  289. #endif
  290.  
  291.         if( err )
  292.         {
  293.             wxLogError(wxT("%s"), err);
  294.         }
  295. #else
  296.         failed = TRUE;
  297.         wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
  298.                       name.c_str());
  299. #endif
  300.     }
  301.     if( success )
  302.         *success = !failed;
  303.  
  304.     return symbol;
  305. }
  306.  
  307.  
  308. // ---------------------------------------------------------------------------
  309. // wxPluginLibrary
  310. // ---------------------------------------------------------------------------
  311.  
  312.  
  313. wxDLImports*  wxPluginLibrary::ms_classes = NULL;
  314.  
  315. class wxPluginLibraryModule : public wxModule
  316. {
  317. public:
  318.     wxPluginLibraryModule() { }
  319.  
  320.     // TODO: create ms_classes on demand, why always preallocate it?
  321.     virtual bool OnInit()
  322.     {
  323.         wxPluginLibrary::ms_classes = new wxDLImports(wxKEY_STRING);
  324.         wxPluginManager::CreateManifest();
  325.         return TRUE;
  326.     }
  327.  
  328.     virtual void OnExit()
  329.     {
  330.         delete wxPluginLibrary::ms_classes;
  331.         wxPluginLibrary::ms_classes = NULL;
  332.         wxPluginManager::ClearManifest();
  333.     }
  334.  
  335. private:
  336.     DECLARE_DYNAMIC_CLASS(wxPluginLibraryModule )
  337. };
  338.  
  339. IMPLEMENT_DYNAMIC_CLASS(wxPluginLibraryModule, wxModule)
  340.  
  341.  
  342. wxPluginLibrary::wxPluginLibrary(const wxString &libname, int flags)
  343.         : m_linkcount(1)
  344.         , m_objcount(0)
  345. {
  346.     m_before = wxClassInfo::sm_first;
  347.     Load( libname, flags );
  348.     m_after = wxClassInfo::sm_first;
  349.  
  350.     if( m_handle != 0 )
  351.     {
  352.         UpdateClassInfo();
  353.         RegisterModules();
  354.     }
  355.     else
  356.     {
  357.         // Flag us for deletion
  358.         --m_linkcount;
  359.     }
  360. }
  361.  
  362. wxPluginLibrary::~wxPluginLibrary()
  363. {
  364.     if( m_handle != 0 )
  365.     {
  366.         UnregisterModules();
  367.         RestoreClassInfo();
  368.     }
  369. }
  370.  
  371. wxPluginLibrary *wxPluginLibrary::RefLib()
  372. {
  373.     wxCHECK_MSG( m_linkcount > 0, NULL,
  374.                  _T("Library had been already deleted!") );
  375.  
  376.     ++m_linkcount;
  377.     return this;
  378. }
  379.  
  380. bool wxPluginLibrary::UnrefLib()
  381. {
  382.     wxASSERT_MSG( m_objcount == 0,
  383.                   _T("Library unloaded before all objects were destroyed") );
  384.  
  385.     if ( --m_linkcount == 0 )
  386.     {
  387.         delete this;
  388.         return TRUE;
  389.     }
  390.  
  391.     return FALSE;
  392. }
  393.  
  394. // ------------------------
  395. // Private methods
  396. // ------------------------
  397.  
  398. void wxPluginLibrary::UpdateClassInfo()
  399. {
  400.     wxClassInfo     *info;
  401.     wxHashTable     *t = wxClassInfo::sm_classTable;
  402.  
  403.         // FIXME: Below is simply a cut and paste specialisation of
  404.         //        wxClassInfo::InitializeClasses.  Once this stabilises,
  405.         //        the two should probably be merged.
  406.         //
  407.         //        Actually it's becoming questionable whether we should merge
  408.         //        this info with the main ClassInfo tables since we can nearly
  409.         //        handle this completely internally now and it does expose
  410.         //        certain (minimal % user_stupidy) risks.
  411.  
  412.     for(info = m_after; info != m_before; info = info->m_next)
  413.     {
  414.         if( info->m_className )
  415.         {
  416.             if( t->Get(info->m_className) == 0 )
  417.                 t->Put(info->m_className, (wxObject *)info);
  418.  
  419.             // Hash all the class names into a local table too so
  420.             // we can quickly find the entry they correspond to.
  421.             (*ms_classes)[info->m_className] = this;
  422.         }
  423.     }
  424.  
  425.     for(info = m_after; info != m_before; info = info->m_next)
  426.     {
  427.         if( info->m_baseClassName1 )
  428.             info->m_baseInfo1 = (wxClassInfo *)t->Get(info->m_baseClassName1);
  429.         if( info->m_baseClassName2 )
  430.             info->m_baseInfo2 = (wxClassInfo *)t->Get(info->m_baseClassName2);
  431.     }
  432. }
  433.  
  434. void wxPluginLibrary::RestoreClassInfo()
  435. {
  436.     wxClassInfo *info;
  437.  
  438.     for(info = m_after; info != m_before; info = info->m_next)
  439.     {
  440.         wxClassInfo::sm_classTable->Delete(info->m_className);
  441.         ms_classes->erase(ms_classes->find(info->m_className));
  442.     }
  443.  
  444.     if( wxClassInfo::sm_first == m_after )
  445.         wxClassInfo::sm_first = m_before;
  446.     else
  447.     {
  448.         info = wxClassInfo::sm_first;
  449.         while( info->m_next && info->m_next != m_after ) info = info->m_next;
  450.  
  451.         wxASSERT_MSG( info, _T("ClassInfo from wxPluginLibrary not found on purge"));
  452.  
  453.         info->m_next = m_before;
  454.     }
  455. }
  456.  
  457. void wxPluginLibrary::RegisterModules()
  458. {
  459.     // Plugin libraries might have wxModules, Register and initialise them if
  460.     // they do.
  461.     //
  462.     // Note that these classes are NOT included in the reference counting since
  463.     // it's implicit that they will be unloaded if and when the last handle to
  464.     // the library is.  We do have to keep a copy of the module's pointer
  465.     // though, as there is currently no way to Unregister it without it.
  466.  
  467.     wxASSERT_MSG( m_linkcount == 1,
  468.                   _T("RegisterModules should only be called for the first load") );
  469.  
  470.     for ( wxClassInfo *info = m_after; info != m_before; info = info->m_next)
  471.     {
  472.         if( info->IsKindOf(CLASSINFO(wxModule)) )
  473.         {
  474.             wxModule *m = wxDynamicCast(info->CreateObject(), wxModule);
  475.  
  476.             wxASSERT_MSG( m, _T("wxDynamicCast of wxModule failed") );
  477.  
  478.             m_wxmodules.Append(m);
  479.             wxModule::RegisterModule(m);
  480.         }
  481.     }
  482.  
  483.     // FIXME: Likewise this is (well was) very similar to InitializeModules()
  484.  
  485.     for ( wxModuleList::Node *node = m_wxmodules.GetFirst();
  486.           node;
  487.           node = node->GetNext())
  488.     {
  489.         if( !node->GetData()->Init() )
  490.         {
  491.             wxLogDebug(_T("wxModule::Init() failed for wxPluginLibrary"));
  492.  
  493.             // XXX: Watch this, a different hash implementation might break it,
  494.             //      a good hash implementation would let us fix it though.
  495.  
  496.             // The name of the game is to remove any uninitialised modules and
  497.             // let the dtor Exit the rest on shutdown, (which we'll initiate
  498.             // shortly).
  499.  
  500.             wxModuleList::Node *oldNode = 0;
  501.             do {
  502.                 node = node->GetNext();
  503.                 delete oldNode;
  504.                 wxModule::UnregisterModule( node->GetData() );
  505.                 oldNode = node;
  506.             } while( node );
  507.  
  508.             --m_linkcount;     // Flag us for deletion
  509.             break;
  510.         }
  511.     }
  512. }
  513.  
  514. void wxPluginLibrary::UnregisterModules()
  515. {
  516.     wxModuleList::Node  *node;
  517.  
  518.     for ( node = m_wxmodules.GetFirst(); node; node = node->GetNext() )
  519.         node->GetData()->Exit();
  520.  
  521.     for ( node = m_wxmodules.GetFirst(); node; node = node->GetNext() )
  522.         wxModule::UnregisterModule( node->GetData() );
  523.  
  524.     m_wxmodules.DeleteContents(TRUE);
  525. }
  526.  
  527.  
  528. // ---------------------------------------------------------------------------
  529. // wxPluginManager
  530. // ---------------------------------------------------------------------------
  531.  
  532. wxDLManifest*   wxPluginManager::ms_manifest = NULL;
  533.  
  534. // ------------------------
  535. // Static accessors
  536. // ------------------------
  537.  
  538. wxPluginLibrary *
  539. wxPluginManager::LoadLibrary(const wxString &libname, int flags)
  540. {
  541.     wxString realname(libname);
  542.  
  543.     if( !(flags & wxDL_VERBATIM) )
  544.         realname += wxDynamicLibrary::GetDllExt();
  545.  
  546.     wxPluginLibrary *entry;
  547.  
  548.     if ( flags & wxDL_NOSHARE )
  549.     {
  550.         entry = NULL;
  551.     }
  552.     else
  553.     {
  554.         entry = FindByName(realname);
  555.     }
  556.  
  557.     if ( entry )
  558.     {
  559.         wxLogTrace(_T("dll"),
  560.                    _T("LoadLibrary(%s): already loaded."), realname.c_str());
  561.  
  562.         entry->RefLib();
  563.     }
  564.     else
  565.     {
  566.         entry = new wxPluginLibrary( libname, flags );
  567.  
  568.         if ( entry->IsLoaded() )
  569.         {
  570.             (*ms_manifest)[realname] = entry;
  571.  
  572.             wxLogTrace(_T("dll"),
  573.                        _T("LoadLibrary(%s): loaded ok."), realname.c_str());
  574.  
  575.         }
  576.         else
  577.         {
  578.             wxLogTrace(_T("dll"),
  579.                        _T("LoadLibrary(%s): failed to load."), realname.c_str());
  580.  
  581.             // we have created entry just above
  582.             if ( !entry->UnrefLib() )
  583.             {
  584.                 // ... so UnrefLib() is supposed to delete it
  585.                 wxFAIL_MSG( _T("Currently linked library is not loaded?") );
  586.             }
  587.  
  588.             entry = NULL;
  589.         }
  590.     }
  591.  
  592.     return entry;
  593. }
  594.  
  595. bool wxPluginManager::UnloadLibrary(const wxString& libname)
  596. {
  597.     wxString realname = libname;
  598.  
  599.     wxPluginLibrary *entry = FindByName(realname);
  600.  
  601.     if ( !entry )
  602.     {
  603.         realname += wxDynamicLibrary::GetDllExt();
  604.  
  605.         entry = FindByName(realname);
  606.     }
  607.  
  608.     if ( !entry )
  609.     {
  610.         wxLogDebug(_T("Attempt to unload library '%s' which is not loaded."),
  611.                    libname.c_str());
  612.  
  613.         return FALSE;
  614.     }
  615.  
  616.     wxLogTrace(_T("dll"), _T("UnloadLibrary(%s)"), realname.c_str());
  617.  
  618.     if ( !entry->UnrefLib() )
  619.     {
  620.         // not really unloaded yet
  621.         return FALSE;
  622.     }
  623.  
  624.     ms_manifest->erase(ms_manifest->find(realname));
  625.  
  626.     return TRUE;
  627. }
  628.  
  629. #if WXWIN_COMPATIBILITY_2_2
  630. wxPluginLibrary *wxPluginManager::GetObjectFromHandle(wxDllType handle)
  631. {
  632.     for ( wxDLManifest::iterator i = ms_manifest->begin();
  633.           i != ms_manifest->end();
  634.           ++i )
  635.     {
  636.         wxPluginLibrary * const lib = i->second;
  637.  
  638.         if ( lib->GetLibHandle() == handle )
  639.             return lib;
  640.     }
  641.  
  642.     return NULL;
  643. }
  644. #endif // WXWIN_COMPATIBILITY_2_2
  645.  
  646. // ------------------------
  647. // Class implementation
  648. // ------------------------
  649.  
  650. bool wxPluginManager::Load(const wxString &libname, int flags)
  651. {
  652.     m_entry = wxPluginManager::LoadLibrary(libname, flags);
  653.  
  654.     return IsLoaded();
  655. }
  656.  
  657. void wxPluginManager::Unload()
  658. {
  659.     wxCHECK_RET( m_entry, _T("unloading an invalid wxPluginManager?") );
  660.  
  661.     for ( wxDLManifest::iterator i = ms_manifest->begin();
  662.           i != ms_manifest->end();
  663.           ++i )
  664.     {
  665.         if ( i->second == m_entry )
  666.         {
  667.             ms_manifest->erase(i);
  668.             return;
  669.         }
  670.     }
  671.  
  672.     m_entry->UnrefLib();
  673.  
  674.     m_entry = NULL;
  675. }
  676.  
  677. // ---------------------------------------------------------------------------
  678. // wxDllLoader   (all these methods are static)
  679. // ---------------------------------------------------------------------------
  680.  
  681. #if WXWIN_COMPATIBILITY_2_2
  682.  
  683. wxDllType wxDllLoader::LoadLibrary(const wxString &name, bool *success)
  684. {
  685.     wxPluginLibrary *p = wxPluginManager::LoadLibrary
  686.                          (
  687.                             name,
  688.                             wxDL_DEFAULT | wxDL_VERBATIM | wxDL_NOSHARE
  689.                          );
  690.  
  691.     if ( success )
  692.         *success = p != NULL;
  693.  
  694.     return p ? p->GetLibHandle() : 0;
  695. }
  696.  
  697. void wxDllLoader::UnloadLibrary(wxDllType handle)
  698. {
  699.     wxPluginLibrary *p = wxPluginManager::GetObjectFromHandle(handle);
  700.  
  701.     wxCHECK_RET( p, _T("Unloading a library not loaded with wxDllLoader?") );
  702.  
  703.     p->UnrefLib();
  704. }
  705.  
  706. void *
  707. wxDllLoader::GetSymbol(wxDllType dllHandle, const wxString &name, bool *success)
  708. {
  709.     wxPluginLibrary *p = wxPluginManager::GetObjectFromHandle(dllHandle);
  710.  
  711.     if ( !p )
  712.     {
  713.         wxFAIL_MSG( _T("Using a library not loaded with wxDllLoader?") );
  714.  
  715.         if ( success )
  716.             *success = FALSE;
  717.  
  718.         return NULL;
  719.     }
  720.  
  721.     return p->GetSymbol(name, success);
  722. }
  723.  
  724. #endif  // WXWIN_COMPATIBILITY_2_2
  725.  
  726. #endif  // wxUSE_DYNAMIC_LOADER
  727.  
  728.