00001 //# DynLib.h: Class to handle loadig of dynamic libraries 00002 //# Copyright (C) 2009 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 00028 #ifndef CASA_DYNLIB_H 00029 #define CASA_DYNLIB_H 00030 00031 //# Includes 00032 #include <casacore/casa/aips.h> 00033 #include <string> 00034 00035 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00036 00037 // <summary> 00038 // Class to handle loading of dynamic libraries 00039 // </summary> 00040 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00041 // </reviewed> 00042 00043 // <use visibility=export> 00044 00045 // <prerequisite> 00046 // <li> Basic knowledge of the dlopen function family 00047 // </prerequisite> 00048 00049 // <synopsis> 00050 // This class makes it possible to load a dynamic library and execute an 00051 // initialization function. Furthermore, one can get a pointer to any function 00052 // in the dynamic library and close the library. 00053 // 00054 // The search path of the shared library is as follows: 00055 // <ul> 00056 // <li> If the environment library CASACORE_LDPATH is defined, it is tried to 00057 // find the library using that path. 00058 // <li> If not defined or not found, the system's (DY)LD_LIBRARY_PATH is used. 00059 // <li> The library looked for has the name 'prefix'libname'suffix'. 00060 // <br>As prefix first "lib" is used, thereafter the given one 00061 // (e.g., "libcasa_"). 00062 // <br>As suffix first ".so" is used, thereafter ".dylib" (for OS-X). 00063 // </ul> 00064 // 00065 // It is a wrapper around functions dlopen, dlsym, and dlclose. 00066 // If dlopen and so are not supported on a platform, the class acts as if 00067 // the shared library could not be found. 00068 // </synopsis> 00069 00070 // <example> 00071 // <srcblock> 00072 // DynLib dl("derivedmscal", "libcasa_", "register_derivedmscal"); 00073 // AlwaysAssert (dl.getHandle()); 00074 // </srcblock> 00075 // Using this 00076 // loads the shared library <src>libcasa_derivedmscal.so</src> and 00077 // executes the given register initialization function. 00078 // </example> 00079 00080 // <motivation> 00081 // dlopen is a standard UNIX system call, but some operating systems 00082 // do not support it or have different function names (notably Windows). 00083 // In this way use of dynamic libraries is centralized and can easily b 00084 // tailored as needed. 00085 // </motivation> 00086 00087 class DynLib 00088 { 00089 public: 00090 00091 // Load the dynamic library. It is tried with prefixes "lib" and <src>prefix</src> 00092 // and suffixes ".so" and ".dylib". 00093 // If not loaded successfully, the internal handle is NULL. 00094 // <br>If a non-empty funcName is given, that function is looked up and 00095 // executed. Its signature must be <src>void func()</src>. Note that the 00096 // function name should not be mangled, thus declared <src>extern "C"</src>. 00097 // An exception is thrown if the library is loaded successfully, but 00098 // <src>funcName</src> could not be found. 00099 // <br>If <src>closeOnDestruction=True</src>, the dynamic library is closed 00100 // on destruction of the DynLib object. 00101 DynLib (const std::string& library, 00102 const std::string& prefix=std::string(), 00103 const std::string& funcName=std::string(), 00104 bool closeOnDestruction=True); 00105 00106 // Load the dynamic library with the given name, prefix, and suffix. 00107 // If not loaded successfully, the internal handle is NULL. 00108 // <br>If <src>closeOnDestruction=True</src>, the dynamic library is closed 00109 // when the DynLib object is destructed. 00110 DynLib (const std::string& library, 00111 Bool closeOnDestruction, 00112 const std::string& prefix="lib", 00113 #ifdef __APPLE__ 00114 const std::string& suffix=".dylib"); 00115 #else 00116 const std::string& suffix=".so"); 00117 #endif 00118 00119 // Close the dynamic library if told so in the constructor. 00120 ~DynLib(); 00121 00122 // Get a pointer to a function in the dynamic library. 00123 // The pointer has to be casted with a reinterpret_cast to a function 00124 // pointer with the correct signature. When compiling with -pedantic the 00125 // compiler will give a warning for such a cast, because on some systems 00126 // (in particular some micro-controllers) a data pointer differs from a 00127 // function pointer. However, that problem cannot be solved. 00128 // For example: 00129 // <srcblock> 00130 // typedef Int MyFunc(Int, Int); 00131 // void* initfunc = DynLib::getFunc (mod, ("register_"+name).c_str()); 00132 // if (initFunc) { 00133 // MyFunc* func = reinterpret_cast<MyFunc*>(initfunc); 00134 // Int result = func(1,2); 00135 // } 00136 // </srcblock> 00137 // casts to a function returning Int and taking two Ints. 00138 // <br>A null pointer is returned if the function could not be found. 00139 void* getFunc (const std::string& funcName); 00140 00141 // Get the dynamic library handle. 00142 void* getHandle() const 00143 { return itsHandle; } 00144 00145 // Get the possible error. 00146 const std::string& getError() const 00147 { return itsError; } 00148 00149 private: 00150 // Open (load)the dynamic library. 00151 void open (const std::string& name); 00152 00153 // Close (unload) the dynamic library (if opened). 00154 void close(); 00155 00156 // Try if the library can be opened using CASACORE_LDPATH. 00157 std::string tryCasacorePath (const std::string& library, 00158 const std::string& prefix); 00159 00160 //# Handle to dynamic library; note that the pointer is not owned, so the 00161 //# generated copy ctor and assignment are fine. 00162 void* itsHandle; 00163 Bool itsDoClose; 00164 std::string itsError; 00165 }; 00166 00167 } //# NAMESPACE CASACORE - END 00168 00169 #endif