Simbody
|
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