Plugin.h
Go to the documentation of this file.00001 #ifndef SimTK_SimTKCOMMON_PLUGIN_H_
00002 #define SimTK_SimTKCOMMON_PLUGIN_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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();
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;
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;
00446 Array_<std::string> m_searchPath;
00447
00448 std::string m_loadedPathname;
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 }
00511
00512 #endif // SimTK_SimTKCOMMON_PLUGIN_H_
00513
00514