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