Simbody

Plugin.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_PLUGIN_H_
00002 #define SimTK_SimTKCOMMON_PLUGIN_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                          SimTK Core: SimTKcommon                           *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2009 Stanford University and the Authors.           *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00035 #include "SimTKcommon/internal/common.h"
00036 #include "SimTKcommon/internal/Array.h"
00037 #include <string>
00038 #include <stdexcept>
00039 
00040 namespace SimTK {
00041 
00092 class SimTK_SimTKCOMMON_EXPORT Pathname {
00093 public:
00132     static void deconstructPathname(    const std::string& name,
00133                                         bool&        isAbsolutePath,
00134                                         std::string& directory,
00135                                         std::string& fileName,
00136                                         std::string& extension);
00137 
00155     static std::string getAbsolutePathname(const std::string& pathname) {
00156         bool isAbsolutePath;
00157         std::string directory, fileName, extension;
00158         deconstructPathname(pathname, isAbsolutePath, directory, fileName, extension);
00159         if (!isAbsolutePath)
00160             directory = getCurrentWorkingDirectory() + directory;
00161         return directory + fileName + extension;
00162     }
00163 
00167     static std::string getAbsoluteDirectoryPathname(const std::string& dirPathname) {
00168         std::string absPath = getAbsolutePathname(dirPathname);
00169         if (!absPath.empty() && absPath[absPath.size()-1] != getPathSeparatorChar())
00170             absPath += getPathSeparatorChar();
00171         return absPath;
00172     }
00173 
00177     static std::string getDefaultInstallDir();
00178 
00181     static std::string addDirectoryOffset(const std::string& base, const std::string& offset);
00182 
00186     static std::string getInstallDir(const std::string& envInstallDir,
00187                                      const std::string& offsetFromDefaultInstallDir);
00188 
00190     static std::string getThisExecutablePath();
00193     static std::string getThisExecutableDirectory();
00201     static std::string getCurrentWorkingDirectory(const std::string& drive="");
00205     static std::string getRootDirectory(const std::string& drive="");
00208     static std::string getCurrentDriveLetter();
00211     static std::string getCurrentDrive();
00214     static bool environmentVariableExists(const std::string& name);
00220     static std::string getEnvironmentVariable(const std::string& name);
00224     static std::string getPathSeparator();
00228     static char getPathSeparatorChar();
00230     static bool isPathSeparator(char c) {
00231         return c=='/' || c=='\\';
00232     }
00233 };
00234 
00292 class SimTK_SimTKCOMMON_EXPORT Plugin {
00293 public:
00294     explicit Plugin(const std::string& defaultPathname="");
00295     ~Plugin();  // unloads the plugin if it was loaded
00296 
00310     bool load(const std::string& name="");
00311 
00316     void unload();
00317 
00320     bool isLoaded()                   const {return m_handle != 0;}
00321 
00322     const std::string& getLoadedPathname() const {
00323         return m_loadedPathname; // empty if nothing loaded
00324     }
00325 
00328     std::string getLastErrorMessage() const {return m_lastMessage;}
00329 
00335     void setSearchPath(const Array_<std::string>& pathIn) {
00336         m_searchPath.clear();
00337         for (unsigned i=0; i < pathIn.size(); ++i) 
00338             addSearchDirectory(pathIn[i]);
00339     }
00340 
00341     const Array_<std::string>& getSearchPath() const {return m_searchPath;}
00342 
00346     void addSearchDirectory(const std::string& directory) {
00347         const std::string absDir = Pathname::getAbsoluteDirectoryPathname(directory);
00348         if (!absDir.empty())
00349             m_searchPath.push_back(absDir);
00350     }
00351 
00356     void prependSearchDirectory(const std::string& directory) {
00357         const std::string absDir = Pathname::getAbsoluteDirectoryPathname(directory);
00358         if (!absDir.empty())
00359             m_searchPath.insert(m_searchPath.begin(), absDir);
00360     }
00361 
00362 
00365     static void* loadPluginByFileName(const std::string& name, std::string& errMsg);
00370     static void* loadDebugOrReleasePlugin(const std::string& base, const std::string& extension,
00371                                           std::string& loadedFileName, std::string& errMsg);
00374     static void* getSymbolAddress(void* handle, const std::string& name, std::string& errMsg);
00377     static void unloadPlugin(void* handle);
00378 
00420     static bool deconstructLibraryName( const std::string& name,
00421                                         bool&        isAbsolutePath,
00422                                         std::string& directory,
00423                                         std::string& libPrefix,
00424                                         std::string& baseName,
00425                                         std::string& debugSuffix,
00426                                         std::string& extension);
00427 
00431     static std::string getDynamicLibPrefix();
00432 
00436     static std::string getDynamicLibExtension();
00437 
00442     static std::string getDynamicLibDebugSuffix();
00443 
00444 protected:
00445     std::string                 m_defaultName; // if any
00446     Array_<std::string>         m_searchPath;
00447 
00448     std::string                 m_loadedPathname; // absolute
00449     void*                       m_handle;
00450     mutable std::string         m_lastMessage;
00451 
00452 };
00453 
00454 
00455 #define SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName)          \
00456     struct FuncName##__Holder__ {                       \
00457         FuncName##__Holder__() : fp(0) {}               \
00458         bool loadSym(void* h, std::string& msg) const { \
00459             if(!fp) fp =(FuncName##__Type__)            \
00460                 Plugin::getSymbolAddress(h, #FuncName, msg);   \
00461             return (fp!=0);                             \
00462         }                                               \
00463         mutable FuncName##__Type__ fp;                  \
00464     } FuncName##__Ref__
00465 #define SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)            \
00466     if (!FuncName##__Ref__.loadSym(m_handle,m_lastMessage)) \
00467     throw std::runtime_error                            \
00468       ("Plugin function " #FuncName " not found: " + m_lastMessage); \
00469     return FuncName##__Ref__.fp
00470 #define SimTK_PLUGIN_XXX_MAKE_SYMTEST(Symbol)           \
00471     bool has_##Symbol() const {                          \
00472         return Symbol##__Ref__.loadSym(m_handle,m_lastMessage);   \
00473     }
00474 
00475 #define SimTK_PLUGIN_DEFINE_SYMBOL(Type, SymName)   \
00476     typedef Type SymName##__Type__;                 \
00477     SimTK_PLUGIN_XXX_MAKE_HOLDER(SymName);          \
00478     const Type& SymName() const {                   \
00479         if (!SymName##__Ref__.loadSym(m_handle,m_lastMessage))  \
00480         throw std::runtime_error                                \
00481           ("Plugin symbol " #SymName " not found: " + m_lastMessage); \
00482         return *(SymName##__Ref__.fp);              \
00483     }
00484 
00485 #define SimTK_PLUGIN_DEFINE_FUNCTION(RetType, FuncName) \
00486     typedef RetType (*FuncName##__Type__)();            \
00487     SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName);             \
00488     RetType FuncName() const {                          \
00489         SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)();         \
00490     }                                                   \
00491     SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName)
00492 
00493 #define SimTK_PLUGIN_DEFINE_FUNCTION1(RetType, FuncName, Arg1) \
00494     typedef RetType (*FuncName##__Type__)(Arg1);        \
00495     SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName);             \
00496     RetType FuncName(Arg1 a1) const {                   \
00497         SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(a1);       \
00498     }                                                   \
00499     SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName)
00500 
00501 #define SimTK_PLUGIN_DEFINE_FUNCTION2(RetType, FuncName, Arg1, Arg2) \
00502     typedef RetType (*FuncName##__Type__)(Arg1,Arg2);   \
00503     SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName);             \
00504     RetType FuncName(Arg1 a1, Arg2 a2) const {          \
00505         SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(a1,a2);    \
00506     }                                                   \
00507     SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName)
00508 
00509 
00510 } // namespace SimTK
00511 
00512 #endif // SimTK_SimTKCOMMON_PLUGIN_H_
00513 
00514 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines