ncbidll.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:16k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbidll.hpp,v $
  4.  * PRODUCTION Revision 1000.3  2003/12/02 20:27:57  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.21
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef CORELIB___NCBIDLL__HPP
  10. #define CORELIB___NCBIDLL__HPP
  11. /*  $Id: ncbidll.hpp,v 1000.3 2003/12/02 20:27:57 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Author:  Denis Vakatov, Vladimir Ivanov, Anatoliy Kuznetsov
  37.  *
  38.  *
  39.  */
  40. /// @file ncbidll.hpp
  41. /// Define class Dll and for Portable DLL handling.
  42. #include <corelib/ncbistd.hpp>
  43. #include <corelib/ncbifile.hpp>
  44. BEGIN_NCBI_SCOPE
  45. /** @addtogroup Dll
  46.  *
  47.  * @{
  48.  */
  49. // Forward declaration of struct containing OS-specific DLL handle.
  50. struct SDllHandle;
  51. /////////////////////////////////////////////////////////////////////////////
  52. ///
  53. /// CDll --
  54. ///
  55. /// Define class for portable Dll handling.
  56. ///
  57. /// The DLL name is considered the basename if it does not contain embedded
  58. /// '/', '', or ':' symbols. Also, in this case, if the DLL name does not
  59. /// match pattern "lib*.so", "lib*.so.*", or "*.dll" (and if eExactName flag
  60. /// not passed to the constructor), then it will be automagically transformed
  61. /// according to the following rules:
  62. /// - UNIX:        <name>  --->  lib<name>.so
  63. /// - MS Windows:  <name>  --->  <name>.dll
  64. ///
  65. ///  If the DLL is specified by its basename, then it will be searched
  66. ///  (after the transformation described above) in the following locations:
  67. ///
  68. ///    UNIX:
  69. ///      1) the directories that are listed in the LD_LIBRARY_PATH environment
  70. ///         variable (analyzed once at the process startup);
  71. ///      2) the directory from which the application loaded;
  72. ///      3) hard-coded (e.g. with `ldconfig' on Linux) paths.
  73. ///
  74. ///    MS Windows:
  75. ///      1) the directory from which the application is loaded;
  76. ///      2) the current directory; 
  77. ///      3) the Windows system directory;
  78. ///      4) the Windows directory;
  79. ///      5) the directories that are listed in the PATH environment variable.
  80. ///
  81. /// NOTE: All methods of this class except the destructor throw exception
  82. /// CCoreException::eDll on error.
  83. class CDll
  84. {
  85. public:
  86.     /// When to load DLL.
  87.     enum ELoad {
  88.         eLoadNow,      ///< Load DLL immediately in the constructor
  89.         eLoadLater     ///< Load DLL later, using method Load()
  90.     };
  91.     /// Whether to unload DLL in the destructor.
  92.     enum EAutoUnload {
  93.         eAutoUnload,   ///< Do unload DLL in the destructor
  94.         eNoAutoUnload  ///< Do not unload DLL in the destructor
  95.     };
  96.     /// Whether to transform the DLL basename.
  97.     ///
  98.     /// Transformation is done according to the following:
  99.     ///
  100.     ///   UNIX:        <name>  --->  lib<name>.so
  101.     ///   MS Windows:  <name>  --->  <name>.dll
  102.     enum EBasename {
  103.         eBasename,  ///< Treat as basename (if it looks like one)
  104.         eExactName  ///< Use the name "as is" (no prefix/suffix adding)
  105.     };
  106.     /// Constructor.
  107.     ///
  108.     /// @param name
  109.     ///   Can be either DLL basename or an absolute file path.
  110.     /// @param when_to_load
  111.     ///   Choice to load now or later using Load().
  112.     /// @param auto_unload
  113.     ///   Choice to unload DLL in destructor.
  114.     /// @param treat_as
  115.     ///   Choice to transform the DLL base name.
  116.     /// @sa
  117.     ///   Basename discussion in CDll header,
  118.     ///   Eload, EAutoUnload, EBasename definition.
  119.     NCBI_XNCBI_EXPORT
  120.     CDll(const string& name,
  121.          ELoad         when_to_load = eLoadNow,
  122.          EAutoUnload   auto_unload  = eNoAutoUnload,
  123.          EBasename     treate_as    = eBasename);
  124.     /// Constructor.
  125.     ///
  126.     /// The absolute file path to the DLL will be formed using the "path"
  127.     /// and "name" parameters in the following way:
  128.     /// - UNIX:   <path>/lib<name>.so ; <path>/<name> if "name" is not basename
  129.     /// - MS-Win: <path><name>.dll   ; <path><name> if "name" is not basename
  130.     ///
  131.     /// @param path
  132.     ///   Path to DLL.
  133.     /// @param name
  134.     ///   Name of DLL.
  135.     /// @param when_to_load
  136.     ///   Choice to load now or later using Load().
  137.     /// @param auto_load
  138.     ///   Choice to unload DLL in destructor.
  139.     /// @param treat_as
  140.     ///   Choice to transform the DLL base name.
  141.     /// @sa
  142.     ///   Basename discussion in CDll header,
  143.     ///   Eload, EAutoUnload, EBasename definition.
  144.     NCBI_XNCBI_EXPORT
  145.     CDll(const string& path, const string& name,
  146.          ELoad         when_to_load = eLoadNow,
  147.          EAutoUnload   auto_unload  = eNoAutoUnload,
  148.          EBasename     treate_as    = eBasename);
  149.     /// Destructor.
  150.     ///
  151.     /// Unload DLL if constructor was passed "eAutoUnload".
  152.     /// Destructor does not throw any exceptions.
  153.     NCBI_XNCBI_EXPORT ~CDll(void);
  154.     /// Load DLL.
  155.     ///
  156.     /// Load the DLL using the name specified in the constructor's DLL "name".
  157.     /// If Load() is called more than once without calling Unload() in between,
  158.     /// then it will do nothing.
  159.     NCBI_XNCBI_EXPORT void Load(void);
  160.     /// Unload DLL.
  161.     ///
  162.     /// Do nothing and do not generate errors if the DLL is not loaded.
  163.     NCBI_XNCBI_EXPORT void Unload(void);
  164.     /// Get DLLs entry point (function).
  165.     ///
  166.     /// Get the entry point (a function) with name "name" in the DLL and
  167.     /// return the entry point's address on success, or return NULL on error.
  168.     /// If the DLL is not loaded yet, then this method will call Load(),
  169.     /// which can result in throwing an exception if Load() fails.
  170.     /// @sa
  171.     ///   GetEntryPoint_Data()
  172.     template <class TFunc>
  173.     TFunc GetEntryPoint_Func(const string& name, TFunc* func)
  174.     {
  175.         TEntryPoint ptr = GetEntryPoint(name);
  176.         if ( func ) {
  177.             *func = (TFunc)ptr.func; 
  178.         }
  179.         return (TFunc)ptr.func;
  180.     }
  181.     /// Get DLLs entry point (data).
  182.     ///
  183.     /// Get the entry point (a data) with name "name" in the DLL and
  184.     /// return the entry point's address on success, or return NULL on error.
  185.     /// If the DLL is not loaded yet, then this method will call Load(),
  186.     /// which can result in throwing an exception if Load() fails.
  187.     /// @sa
  188.     ///   GetEntryPoint_Func()
  189.     template <class TData>
  190.     TData GetEntryPoint_Data(const string& name, TData* data)
  191.     {
  192.         TEntryPoint ptr = GetEntryPoint(name);
  193.         if ( data ) {
  194.             *data = static_cast<TData> (ptr.data); 
  195.         }
  196.         return static_cast<TData> (ptr.data);
  197.     }
  198.     /// Fake, uncallable function pointer
  199.     typedef void (*FEntryPoint)(char**** Do_Not_Call_This);
  200.     /// Entry point -- pointer to either a function or a data
  201.     union TEntryPoint {
  202.         FEntryPoint func;  ///< Do not call this func without type cast!
  203.         void*       data;
  204.     };
  205.     /// Helper find method for getting a DLLs entry point.
  206.     ///
  207.     /// Get the entry point (e.g. a function) with name "name" in the DLL.
  208.     /// @param name
  209.     ///   Name of DLL.
  210.     /// @param pointer_size
  211.     ///   Size of pointer.
  212.     /// @return
  213.     ///   The entry point's address on success, or return NULL on error.
  214.     /// @sa
  215.     ///   GetEntryPoint_Func(), GetEntryPoint_Data()
  216.     NCBI_XNCBI_EXPORT
  217.     TEntryPoint GetEntryPoint(const string& name);
  218.     /// Get the name of the DLL file 
  219.     NCBI_XNCBI_EXPORT
  220.     const string& GetName() const { return m_Name; }
  221. private:
  222.     /// Helper method to throw exception with system-specific error message.
  223.     void  x_ThrowException(const string& what);
  224.     /// Helper method to initialize object.
  225.     ///
  226.     /// Called from constructor.
  227.     /// @param path
  228.     ///   Path to DLL.
  229.     /// @param name
  230.     ///   Name of DLL.
  231.     /// @param when_to_load
  232.     ///   Choice to load now or later using Load().
  233.     /// @param auto_load
  234.     ///   Choice to unload DLL in destructor.
  235.     /// @param treat_as
  236.     ///   Choice to transform the DLL base name.
  237.     /// @sa
  238.     ///   Eload, EAutoUnload, EBasename definition.
  239.     void  x_Init(const string& path, const string& name, 
  240.                  ELoad       when_to_load, 
  241.                  EAutoUnload auto_unload, 
  242.                  EBasename   treate_as);
  243. protected:
  244.     /// Private copy constructor to prohibit copy.
  245.     CDll(const CDll&);
  246.     /// Private assignment operator to prohibit assignment.
  247.     CDll& operator= (const CDll&);
  248. private:
  249.     string      m_Name;       ///< DLL name
  250.     SDllHandle* m_Handle;     ///< DLL handle
  251.     bool        m_AutoUnload; ///< Whether to unload DLL in the destructor
  252. };
  253. /////////////////////////////////////////////////////////////////////////////
  254. ///
  255. /// Class for entry point resolution when there are several DLL candidates.
  256. ///
  257. /// If Dll resolver finds DLL with the specified entry point it is
  258. /// stored in the internal list (provided by GetResolvedEntries method).
  259. /// All DLL libraries are unloaded upon resolver's destruction
  260. ///
  261. class CDllResolver
  262. {
  263. public:
  264.     /// DLL entry point name -> function pair
  265.     struct SNamedEntryPoint
  266.     {
  267.         string               name;          ///< Entry point name
  268.         CDll::TEntryPoint    entry_point;   ///< DLL entry point
  269.         SNamedEntryPoint(const string&       x_name,
  270.                          CDll::TEntryPoint   x_entry_point)
  271.         : name(x_name)
  272.         {
  273.             entry_point.data = x_entry_point.data;
  274.         }
  275.     };
  276.     /// DLL resolution descriptor.
  277.     struct SResolvedEntry
  278.     {
  279.         CDll*                     dll;           ///< Loaded DLL instance
  280.         vector<SNamedEntryPoint>  entry_points;  ///< list of DLL entry points
  281.         SResolvedEntry(CDll* dll_ptr = 0)
  282.         : dll(dll_ptr)
  283.         {}
  284.     };
  285.     /// Container, keeps list of all resolved entry points.
  286.     typedef vector<SResolvedEntry>  TEntries;
  287.     /// Constructor.
  288.     ///
  289.     /// @param entry_point_name
  290.     ///   Name of the DLL entry point.
  291.     NCBI_XNCBI_EXPORT CDllResolver(const string& entry_point_name);
  292.     /// Constructor.
  293.     ///
  294.     /// @param entry_point_names
  295.     ///   List of alternative DLL entry points.
  296.     NCBI_XNCBI_EXPORT CDllResolver(const vector<string>& entry_point_names); 
  297.     
  298.     NCBI_XNCBI_EXPORT ~CDllResolver();
  299.     /// Try to load DLL from the specified file and resolve the entry point.
  300.     ///
  301.     /// If DLL resolution successfull loaded entry point is registered in the
  302.     /// internal list of resolved entries.
  303.     ///
  304.     /// @param file_name
  305.     ///   Name of the DLL file. Can be full name with path of the base name.
  306.     /// @return
  307.     ///   TRUE if DLL is succesfully loaded and entry point resolved.
  308.     /// @sa
  309.     ///   GetResolvedEntries
  310.     NCBI_XNCBI_EXPORT
  311.     bool TryCandidate(const string& file_name);
  312.     /// Try to resolve file candidates.
  313.     ///
  314.     /// @param candidates
  315.     ///    Container with file names to try.
  316.     /// @sa
  317.     ///   GetResolvedEntries
  318.     template<class TClass>
  319.     void Try(const TClass& candidates)
  320.     {
  321.         typename TClass::const_iterator it = candidates.begin();
  322.         typename TClass::const_iterator it_end = candidates.end();
  323.         for (; it != it_end; ++it) {
  324.             TryCandidate(*it);
  325.         }
  326.     }
  327.     /// Try to resolve all files matching the specified masks in the
  328.     /// specified directories.
  329.     ///
  330.     /// @param paths
  331.     ///   Container with directory names.
  332.     /// @param masks
  333.     ///   Container with file candidate masks.
  334.     /// @sa
  335.     ///   GetResolvedEntries
  336.     template<class TClass1, class TClass2>
  337.     void FindCandidates(const TClass1& paths, const TClass2& masks)
  338.     {
  339.         vector<string> candidates;
  340.         FindFiles(candidates, paths.begin(), paths.end(), 
  341.                               masks.begin(), masks.end());
  342.         Try(candidates);
  343.     }
  344.     /// Get all resolved entry points.
  345.     NCBI_XNCBI_EXPORT 
  346.     const TEntries& GetResolvedEntries() const 
  347.     { 
  348.         return m_ResolvedEntries; 
  349.     }
  350.     /// Get all resolved entry points.
  351.     NCBI_XNCBI_EXPORT
  352.     TEntries& GetResolvedEntries() 
  353.     { 
  354.         return m_ResolvedEntries; 
  355.     }
  356.     /// Unload all resolved DLLs.
  357.     NCBI_XNCBI_EXPORT void Unload();
  358. private:
  359.     CDllResolver(const CDllResolver&);
  360.     CDllResolver& operator=(const CDllResolver&);
  361. protected:
  362.     vector<string>  m_EntryPoinNames;   ///< Candidate entry points
  363.     TEntries        m_ResolvedEntries;
  364. };
  365. /* @} */
  366. END_NCBI_SCOPE
  367. /*
  368.  * ===========================================================================
  369.  * $Log: ncbidll.hpp,v $
  370.  * Revision 1000.3  2003/12/02 20:27:57  gouriano
  371.  * PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.21
  372.  *
  373.  * Revision 1.21  2003/12/01 16:39:00  kuznets
  374.  * CDllResolver changed to try all entry points
  375.  * (prev. version stoped on first successfull).
  376.  *
  377.  * Revision 1.20  2003/11/19 16:49:26  ivanov
  378.  * Specify NCBI_XNCBI_EXPORT for each method in the CDll and CDllResolver.
  379.  * In the MSVC, templates cannot be used with functions declared with
  380.  * __declspec (dllimport) or __declspec (dllexport).
  381.  *
  382.  * Revision 1.19  2003/11/19 15:42:01  kuznets
  383.  * Using new entry point structure (union) in CDllResolver
  384.  *
  385.  * Revision 1.18  2003/11/19 13:50:28  ivanov
  386.  * GetEntryPoint() revamp: added GetEntryPoin_[Func|Data]()
  387.  *
  388.  * Revision 1.17  2003/11/12 17:40:36  kuznets
  389.  * + CDllResolver::Unload()
  390.  *
  391.  * Revision 1.16  2003/11/10 15:28:24  kuznets
  392.  * Fixed misprint
  393.  *
  394.  * Revision 1.15  2003/11/10 15:04:35  kuznets
  395.  * CDllResolver changed to inspect DLL candidate for several alternative
  396.  * entry points
  397.  *
  398.  * Revision 1.14  2003/11/07 17:11:53  kuznets
  399.  * Minor cleanup.
  400.  *
  401.  * Revision 1.13  2003/11/06 13:22:36  kuznets
  402.  * Fixed minor compilation bug
  403.  *
  404.  * Revision 1.12  2003/11/06 12:59:15  kuznets
  405.  * Added new class CDllResolver
  406.  * (searches for DLLs with the specified entry point)
  407.  *
  408.  * Revision 1.11  2003/09/11 16:17:33  ivanov
  409.  * Fixed lines wrapped at 79th column
  410.  *
  411.  * Revision 1.10  2003/07/28 19:07:04  siyan
  412.  * Documentation changes.
  413.  *
  414.  * Revision 1.9  2003/03/31 15:44:33  siyan
  415.  * Added doxygen support
  416.  *
  417.  * Revision 1.8  2002/12/18 22:53:21  dicuccio
  418.  * Added export specifier for building DLLs in windows.  Added global list of
  419.  * all such specifiers in mswin_exports.hpp, included through ncbistl.hpp
  420.  *
  421.  * Revision 1.7  2002/10/29 15:59:06  ivanov
  422.  * Prohibited copy constructor and assignment operator
  423.  *
  424.  * Revision 1.6  2002/07/15 18:17:51  gouriano
  425.  * renamed CNcbiException and its descendents
  426.  *
  427.  * Revision 1.5  2002/07/11 14:17:54  gouriano
  428.  * exceptions replaced by CNcbiException-type ones
  429.  *
  430.  * Revision 1.4  2002/04/11 20:39:17  ivanov
  431.  * CVS log moved to end of the file
  432.  *
  433.  * Revision 1.3  2002/01/20 07:18:10  vakatov
  434.  * CDll::GetEntryPoint() -- fool-proof cast of void ptr to func ptr
  435.  *
  436.  * Revision 1.2  2002/01/16 18:48:13  ivanov
  437.  * Added new constructor and related "basename" rules for DLL names. 
  438.  * Polished source code.
  439.  *
  440.  * Revision 1.1  2002/01/15 19:06:07  ivanov
  441.  * Initial revision
  442.  *
  443.  * ===========================================================================
  444.  */
  445. #endif  /* CORELIB___NCBIDLL__HPP */