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

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        dynlib.cpp
  3. // Purpose:     Dynamic library management
  4. // Author:      Guilhem Lavaux
  5. // Modified by:
  6. // Created:     20/07/98
  7. // RCS-ID:      $Id: dynlib.cpp,v 1.67.2.2 2002/12/19 23:43:33 VS Exp $
  8. // Copyright:   (c) Guilhem Lavaux
  9. // Licence:     wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21. #   pragma implementation "dynlib.h"
  22. #endif
  23.  
  24. #include  "wx/wxprec.h"
  25.  
  26. #ifdef __BORLANDC__
  27.   #pragma hdrstop
  28. #endif
  29.  
  30. #if wxUSE_DYNLIB_CLASS && !wxUSE_DYNAMIC_LOADER
  31.  
  32. #if defined(__WINDOWS__)
  33.     #include "wx/msw/private.h"
  34. #endif
  35.  
  36. #include "wx/dynlib.h"
  37. #include "wx/filefn.h"
  38. #include "wx/intl.h"
  39. #include "wx/log.h"
  40.  
  41. #if defined(__WXMAC__)
  42.     #include "wx/mac/private.h"
  43. #endif
  44.  
  45. // ----------------------------------------------------------------------------
  46. // conditional compilation
  47. // ----------------------------------------------------------------------------
  48.  
  49. #if defined(__WXPM__) || defined(__EMX__)
  50. #  define INCL_DOS
  51. #  include <os2.h>
  52. #  define wxDllOpen(error, lib, handle)     DosLoadModule(error, sizeof(error), lib, &handle)
  53. #  define wxDllGetSymbol(handle, modaddr)   DosQueryProcAddr(handle, 1L, NULL, (PFN*)modaddr)
  54. #  define wxDllClose(handle)                DosFreeModule(handle)
  55. #elif defined(HAVE_DLOPEN)
  56.     // note about dlopen() flags: we use RTLD_NOW to have more Windows-like
  57.     // behaviour (Win won't let you load a library with missing symbols) and
  58.     // RTLD_GLOBAL because it is needed sometimes and probably doesn't hurt
  59.     // otherwise. On True64-Unix RTLD_GLOBAL is not allowed and on VMS the
  60.     // second argument on dlopen is ignored.
  61. #ifdef __VMS
  62. # define wxDllOpen(lib)                dlopen(lib.fn_str(), 0 )
  63. #elif defined( __osf__ )
  64. # define wxDllOpen(lib)                dlopen(lib.fn_str(), RTLD_LAZY )
  65. #else
  66. # define wxDllOpen(lib)                dlopen(lib.fn_str(), RTLD_LAZY | RTLD_GLOBAL)
  67. #endif
  68. #define wxDllGetSymbol(handle, name)  dlsym(handle, name)
  69. #   define wxDllClose                    dlclose
  70. #elif defined(HAVE_SHL_LOAD)
  71. #   define wxDllOpen(lib)                shl_load(lib.fn_str(), BIND_DEFERRED, 0)
  72. #   define wxDllClose                    shl_unload
  73.  
  74. static inline void *wxDllGetSymbol(shl_t handle, const wxString& name)
  75. {
  76.     void *sym;
  77.     if ( shl_findsym(&handle, name.mb_str(), TYPE_UNDEFINED, &sym) == 0 )
  78.         return sym;
  79.     else
  80.         return 0;
  81. }
  82.  
  83. #elif defined(__DARWIN__)
  84. /* Porting notes:
  85.  *   The dlopen port is a port from dl_next.xs by Anno Siegel.
  86.  *   dl_next.xs is itself a port from dl_dlopen.xs by Paul Marquess.
  87.  *   The method used here is just to supply the sun style dlopen etc.
  88.  *   functions in terms of Darwin NS*.
  89.  */
  90. void *dlopen(const char *path, int mode /* mode is ignored */);
  91. void *dlsym(void *handle, const char *symbol);
  92. int   dlclose(void *handle);
  93. const char *dlerror(void);
  94.  
  95. #   define wxDllOpen(lib)                dlopen(lib.fn_str(), 0)
  96. #   define wxDllGetSymbol(handle, name)  dlsym(handle, name)
  97. #   define wxDllClose                    dlclose
  98. #elif defined(__WINDOWS__)
  99.     // using LoadLibraryEx under Win32 to avoid name clash with LoadLibrary
  100. #   ifdef __WIN32__
  101. #ifdef _UNICODE
  102. #      define wxDllOpen(lib)                  ::LoadLibraryExW(lib, 0, 0)
  103. #else
  104. #      define wxDllOpen(lib)                  ::LoadLibraryExA(lib, 0, 0)
  105. #endif
  106. #   else   // Win16
  107. #      define wxDllOpen(lib)                  ::LoadLibrary(lib)
  108. #   endif  // Win32/16
  109. #   define wxDllGetSymbol(handle, name)    ::GetProcAddress(handle, name)
  110. #   define wxDllClose                      ::FreeLibrary
  111. #elif defined(__WXMAC__)
  112. #   define wxDllClose(handle)               CloseConnection(&((CFragConnectionID)handle))
  113. #else
  114. #   error "Don't know how to load shared libraries on this platform."
  115. #endif // OS
  116.  
  117. // ---------------------------------------------------------------------------
  118. // Global variables
  119. // ---------------------------------------------------------------------------
  120.  
  121. wxLibraries wxTheLibraries;
  122.  
  123. // ============================================================================
  124. // implementation
  125. // ============================================================================
  126.  
  127. // construct the full name from the base shared object name: adds a .dll
  128. // suffix under Windows or .so under Unix
  129. static wxString ConstructLibraryName(const wxString& basename)
  130. {
  131.     wxString fullname;
  132.     fullname << basename << wxDllLoader::GetDllExt();
  133.  
  134.     return fullname;
  135. }
  136.  
  137. // ---------------------------------------------------------------------------
  138. // wxLibrary (one instance per dynamic library)
  139. // ---------------------------------------------------------------------------
  140.  
  141. wxLibrary::wxLibrary(wxDllType handle)
  142. {
  143.     typedef wxClassInfo *(*t_get_first)(void);
  144.     t_get_first get_first;
  145.  
  146.     m_handle = handle;
  147.  
  148.     // Some system may use a local heap for library.
  149.     get_first = (t_get_first)GetSymbol(_T("wxGetClassFirst"));
  150.     // It is a wxWindows DLL.
  151.     if (get_first)
  152.         PrepareClasses(get_first());
  153. }
  154.  
  155. wxLibrary::~wxLibrary()
  156. {
  157.     if ( m_handle )
  158.     {
  159.         wxDllClose(m_handle);
  160.     }
  161. }
  162.  
  163. wxObject *wxLibrary::CreateObject(const wxString& name)
  164. {
  165.     wxClassInfo *info = (wxClassInfo *)classTable.Get(name);
  166.  
  167.     if (!info)
  168.         return NULL;
  169.  
  170.     return info->CreateObject();
  171. }
  172.  
  173. void wxLibrary::PrepareClasses(wxClassInfo *first)
  174. {
  175.     // Index all class infos by their class name
  176.     wxClassInfo *info = first;
  177.     while (info)
  178.     {
  179.         if (info->m_className)
  180.             classTable.Put(info->m_className, (wxObject *)info);
  181.         info = info->m_next;
  182.     }
  183.  
  184.     // Set base pointers for each wxClassInfo
  185.     info = first;
  186.     while (info)
  187.     {
  188.         if (info->GetBaseClassName1())
  189.             info->m_baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
  190.         if (info->GetBaseClassName2())
  191.             info->m_baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
  192.         info = info->m_next;
  193.     }
  194. }
  195.  
  196. void *wxLibrary::GetSymbol(const wxString& symbname)
  197. {
  198.    return wxDllLoader::GetSymbol(m_handle, symbname);
  199. }
  200.  
  201. // ---------------------------------------------------------------------------
  202. // wxDllLoader
  203. // ---------------------------------------------------------------------------
  204.  
  205.  
  206. #if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
  207. const wxString wxDllLoader::ms_dllext( _T(".dll") );
  208. #elif defined(__UNIX__)
  209. #if defined(__HPUX__)
  210. const wxString wxDllLoader::ms_dllext( _T(".sl") );
  211. #else
  212. const wxString wxDllLoader::ms_dllext( _T(".so") );
  213. #endif
  214. #elif defined(__WXMAC__)
  215. const wxString wxDllLoader::ms_dllext( _T("") );
  216. #endif
  217.  
  218. /* static */
  219. wxDllType wxDllLoader::GetProgramHandle()
  220. {
  221. #if defined( HAVE_DLOPEN ) && !defined(__EMX__)
  222.    // optain handle for main program
  223.    return dlopen(NULL, RTLD_NOW/*RTLD_LAZY*/);
  224. #elif defined (HAVE_SHL_LOAD)
  225.    // shl_findsymbol with NULL handle looks up in main program
  226.    return 0;
  227. #else
  228.    wxFAIL_MSG( wxT("This method is not implemented under Windows or OS/2"));
  229.    return 0;
  230. #endif
  231. }
  232.  
  233. /* static */
  234. wxDllType wxDllLoader::LoadLibrary(const wxString & libname, bool *success)
  235. {
  236.     wxDllType   handle;
  237.     bool        failed = FALSE;
  238.  
  239. #if defined(__WXMAC__) && !defined(__UNIX__)
  240.     FSSpec      myFSSpec;
  241.     Ptr         myMainAddr;
  242.     Str255      myErrName;
  243.  
  244.     wxMacFilename2FSSpec( libname , &myFSSpec );
  245.  
  246.     if( GetDiskFragment( &myFSSpec,
  247.                          0,
  248.                          kCFragGoesToEOF,
  249.                          "\p",
  250.                          kPrivateCFragCopy,
  251.                          &((CFragConnectionID)handle),
  252.                          &myMainAddr,
  253.                          myErrName ) != noErr )
  254.     {
  255.         p2cstr( myErrName );
  256.         wxLogSysError( _("Failed to load shared library '%s' Error '%s'"),
  257.                        libname.c_str(),
  258.                        (char*)myErrName );
  259.         handle = 0;
  260.         failed = TRUE;
  261.     }
  262.  
  263. #elif defined(__WXPM__) || defined(__EMX__)
  264.     char        zError[256] = "";
  265.     wxDllOpen(zError, libname, handle);
  266.  
  267. #else
  268.     handle = wxDllOpen(libname);
  269.  
  270. #endif
  271.  
  272.     if ( !handle )
  273.     {
  274.         wxString msg(_("Failed to load shared library '%s'"));
  275.  
  276. #ifdef HAVE_DLERROR
  277.         const wxChar *err = dlerror();
  278.         if( err )
  279.         {
  280.             failed = TRUE;
  281.             wxLogError( msg, err );
  282.         }
  283. #else
  284.         failed = TRUE;
  285.         wxLogSysError( msg, libname.c_str() );
  286. #endif
  287.     }
  288.  
  289.     if ( success )
  290.         *success = !failed;
  291.  
  292.     return handle;
  293. }
  294.  
  295.  
  296. /* static */
  297. void wxDllLoader::UnloadLibrary(wxDllType handle)
  298. {
  299.    wxDllClose(handle);
  300. }
  301.  
  302. /* static */
  303. void *wxDllLoader::GetSymbol(wxDllType dllHandle, const wxString &name, bool *success)
  304. {
  305.     bool    failed = FALSE;
  306.     void    *symbol = 0;
  307.  
  308. #if defined(__WXMAC__) && !defined(__UNIX__)
  309.     Ptr                 symAddress;
  310.     CFragSymbolClass    symClass;
  311.     Str255              symName;
  312.  
  313. #if TARGET_CARBON
  314.     c2pstrcpy( (StringPtr) symName, name );
  315. #else
  316.     strcpy( (char *) symName, name );
  317.     c2pstr( (char *) symName );
  318. #endif
  319.     if( FindSymbol( ((CFragConnectionID)dllHandle), symName, &symAddress, &symClass ) == noErr )
  320.         symbol = (void *)symAddress;
  321.  
  322. #elif defined(__WXPM__) || defined(__EMX__)
  323.     wxDllGetSymbol(dllHandle, symbol);
  324.  
  325. #else // Windows or Unix
  326.  
  327.     // mb_str() is necessary in Unicode build
  328.     //
  329.     // "void *" cast is needed by gcc 3.1 + w32api 1.4, don't ask me why
  330.     symbol = (void *)wxDllGetSymbol(dllHandle, name.mb_str());
  331.  
  332. #endif // OS
  333.  
  334.     if ( !symbol )
  335.     {
  336. #ifdef HAVE_DLERROR
  337.         const wxChar *err = dlerror();
  338.         if( err )
  339.         {
  340.             wxLogError(wxT("%s"), err);
  341.         }
  342. #else
  343.         failed = TRUE;
  344.         wxLogSysError(_("Couldn't find symbol '%s' in a dynamic library"),
  345.                       name.c_str());
  346. #endif
  347.     }
  348.  
  349.     if( success )
  350.         *success = !failed;
  351.  
  352.     return symbol;
  353. }
  354.  
  355. // ---------------------------------------------------------------------------
  356. // wxLibraries (only one instance should normally exist)
  357. // ---------------------------------------------------------------------------
  358.  
  359. wxLibraries::wxLibraries():m_loaded(wxKEY_STRING)
  360. {
  361. }
  362.  
  363. wxLibraries::~wxLibraries()
  364. {
  365.     wxNode *node = m_loaded.First();
  366.  
  367.     while (node) {
  368.         wxLibrary *lib = (wxLibrary *)node->Data();
  369.         delete lib;
  370.  
  371.         node = node->Next();
  372.     }
  373. }
  374.  
  375. wxLibrary *wxLibraries::LoadLibrary(const wxString& name)
  376. {
  377.     wxLibrary   *lib;
  378.     wxClassInfo *old_sm_first;
  379.     wxNode      *node = m_loaded.Find(name.GetData());
  380.  
  381.     if (node != NULL)
  382.         return ((wxLibrary *)node->Data());
  383.  
  384.     // If DLL shares data, this is necessary.
  385.     old_sm_first = wxClassInfo::sm_first;
  386.     wxClassInfo::sm_first = NULL;
  387.  
  388.     wxString libname = ConstructLibraryName(name);
  389.  
  390.     bool success = FALSE;
  391.     wxDllType handle = wxDllLoader::LoadLibrary(libname, &success);
  392.     if(success)
  393.     {
  394.        lib = new wxLibrary(handle);
  395.        wxClassInfo::sm_first = old_sm_first;
  396.  
  397.        m_loaded.Append(name.GetData(), lib);
  398.     }
  399.     else
  400.        lib = NULL;
  401.     return lib;
  402. }
  403.  
  404. wxObject *wxLibraries::CreateObject(const wxString& path)
  405. {
  406.     wxNode *node = m_loaded.First();
  407.     wxObject *obj;
  408.  
  409.     while (node) {
  410.         obj = ((wxLibrary *)node->Data())->CreateObject(path);
  411.         if (obj)
  412.             return obj;
  413.  
  414.         node = node->Next();
  415.     }
  416.     return NULL;
  417. }
  418.  
  419. #endif // wxUSE_DYNLIB_CLASS && !wxUSE_DYNAMIC_LOADER
  420.  
  421. #if defined(__DARWIN__) && (wxUSE_DYNLIB_CLASS || wxUSE_DYNAMIC_LOADER)
  422. // ---------------------------------------------------------------------------
  423. // For Darwin/Mac OS X
  424. //   supply the sun style dlopen functions in terms of Darwin NS*
  425. // ---------------------------------------------------------------------------
  426.  
  427. #include <stdio.h>
  428. #include <mach-o/dyld.h>
  429.  
  430. static char dl_last_error[1024];
  431.  
  432. static
  433. void TranslateError(const char *path, int number)
  434. {
  435.     unsigned int index;
  436.     static char *OFIErrorStrings[] =
  437.     {
  438.     "%s(%d): Object Image Load Failure\n",
  439.     "%s(%d): Object Image Load Success\n",
  440.     "%s(%d): Not an recognisable object file\n",
  441.     "%s(%d): No valid architecture\n",
  442.     "%s(%d): Object image has an invalid format\n",
  443.     "%s(%d): Invalid access (permissions?)\n",
  444.     "%s(%d): Unknown error code from NSCreateObjectFileImageFromFile\n",
  445.     };
  446. #define NUM_OFI_ERRORS (sizeof(OFIErrorStrings) / sizeof(OFIErrorStrings[0]))
  447.  
  448.     index = number;
  449.     if (index > NUM_OFI_ERRORS - 1) {
  450.         index = NUM_OFI_ERRORS - 1;
  451.     }
  452.     sprintf(dl_last_error, OFIErrorStrings[index], path, number);
  453. }
  454.  
  455. const char *dlerror()
  456. {
  457.     return dl_last_error;
  458. }
  459.  
  460. void *dlopen(const char *path, int WXUNUSED(mode) /* mode is ignored */)
  461. {
  462.     int dyld_result;
  463.     NSObjectFileImage ofile;
  464.     NSModule handle = NULL;
  465.  
  466.     dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
  467.     if (dyld_result != NSObjectFileImageSuccess)
  468.     {
  469.     TranslateError(path, dyld_result);
  470.     }
  471.     else
  472.     {
  473.     // NSLinkModule will cause the run to abort on any link error's
  474.     // not very friendly but the error recovery functionality is limited.
  475.     handle = NSLinkModule(ofile, path, NSLINKMODULE_OPTION_BINDNOW);
  476.     }
  477.  
  478.     return handle;
  479. }
  480.  
  481. int dlclose(void *handle)
  482. {
  483.     NSUnLinkModule( handle, NSUNLINKMODULE_OPTION_NONE);
  484.     return 0;
  485. }
  486.  
  487. void *dlsym(void *WXUNUSED(handle), const char *symbol)
  488. {
  489.     void *addr;
  490.  
  491.     if (NSIsSymbolNameDefined(symbol)) {
  492.     addr = NSAddressOfSymbol(NSLookupAndBindSymbol(symbol));
  493.     }
  494.     else {
  495.     addr = NULL;
  496.     }
  497.     return addr;
  498. }
  499.  
  500. #endif // defined(__DARWIN__) && (wxUSE_DYNLIB_CLASS || wxUSE_DYNAMIC_LOADER)
  501.