Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_PLUGIN_H_ 00002 #define SimTK_SimTKCOMMON_PLUGIN_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK 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/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2009-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00031 #include "SimTKcommon/internal/common.h" 00032 #include "SimTKcommon/internal/Array.h" 00033 #include "SimTKcommon/internal/Pathname.h" 00034 #include <string> 00035 #include <stdexcept> 00036 00037 namespace SimTK { 00038 00096 class SimTK_SimTKCOMMON_EXPORT Plugin { 00097 public: 00098 explicit Plugin(const std::string& defaultPathname=""); 00099 ~Plugin(); // unloads the plugin if it was loaded 00100 00114 bool load(const std::string& name=""); 00115 00120 void unload(); 00121 00124 bool isLoaded() const {return m_handle != 0;} 00125 00126 const std::string& getLoadedPathname() const { 00127 return m_loadedPathname; // empty if nothing loaded 00128 } 00129 00132 std::string getLastErrorMessage() const {return m_lastMessage;} 00133 00139 void setSearchPath(const Array_<std::string>& pathIn) { 00140 m_searchPath.clear(); 00141 for (unsigned i=0; i < pathIn.size(); ++i) 00142 addSearchDirectory(pathIn[i]); 00143 } 00144 00145 const Array_<std::string>& getSearchPath() const {return m_searchPath;} 00146 00150 void addSearchDirectory(const std::string& directory) { 00151 const std::string absDir = Pathname::getAbsoluteDirectoryPathname(directory); 00152 if (!absDir.empty()) 00153 m_searchPath.push_back(absDir); 00154 } 00155 00160 void prependSearchDirectory(const std::string& directory) { 00161 const std::string absDir = Pathname::getAbsoluteDirectoryPathname(directory); 00162 if (!absDir.empty()) 00163 m_searchPath.insert(m_searchPath.begin(), absDir); 00164 } 00165 00166 00169 static void* loadPluginByFileName(const std::string& name, std::string& errMsg); 00174 static void* loadDebugOrReleasePlugin(const std::string& base, const std::string& extension, 00175 std::string& loadedFileName, std::string& errMsg); 00178 static void* getSymbolAddress(void* handle, const std::string& name, std::string& errMsg); 00181 static void unloadPlugin(void* handle); 00182 00224 static bool deconstructLibraryName( const std::string& name, 00225 bool& isAbsolutePath, 00226 std::string& directory, 00227 std::string& libPrefix, 00228 std::string& baseName, 00229 std::string& debugSuffix, 00230 std::string& extension); 00231 00235 static std::string getDynamicLibPrefix(); 00236 00240 static std::string getDynamicLibExtension(); 00241 00246 static std::string getDynamicLibDebugSuffix(); 00247 00248 protected: 00249 std::string m_defaultName; // if any 00250 Array_<std::string> m_searchPath; 00251 00252 std::string m_loadedPathname; // absolute 00253 void* m_handle; 00254 mutable std::string m_lastMessage; 00255 00256 }; 00257 00258 00259 #define SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName) \ 00260 struct FuncName##__Holder__ { \ 00261 FuncName##__Holder__() : fp(0) {} \ 00262 bool loadSym(void* h, std::string& msg) const { \ 00263 if(!fp) fp =(FuncName##__Type__) \ 00264 Plugin::getSymbolAddress(h, #FuncName, msg); \ 00265 return (fp!=0); \ 00266 } \ 00267 mutable FuncName##__Type__ fp; \ 00268 } FuncName##__Ref__ 00269 #define SimTK_PLUGIN_XXX_MAKE_BODY(FuncName) \ 00270 if (!FuncName##__Ref__.loadSym(m_handle,m_lastMessage)) \ 00271 throw std::runtime_error \ 00272 ("Plugin function " #FuncName " not found: " + m_lastMessage); \ 00273 return FuncName##__Ref__.fp 00274 #define SimTK_PLUGIN_XXX_MAKE_SYMTEST(Symbol) \ 00275 bool has_##Symbol() const { \ 00276 return Symbol##__Ref__.loadSym(m_handle,m_lastMessage); \ 00277 } 00278 00279 #define SimTK_PLUGIN_DEFINE_SYMBOL(Type, SymName) \ 00280 typedef Type SymName##__Type__; \ 00281 SimTK_PLUGIN_XXX_MAKE_HOLDER(SymName); \ 00282 const Type& SymName() const { \ 00283 if (!SymName##__Ref__.loadSym(m_handle,m_lastMessage)) \ 00284 throw std::runtime_error \ 00285 ("Plugin symbol " #SymName " not found: " + m_lastMessage); \ 00286 return *(SymName##__Ref__.fp); \ 00287 } 00288 00289 #define SimTK_PLUGIN_DEFINE_FUNCTION(RetType, FuncName) \ 00290 typedef RetType (*FuncName##__Type__)(); \ 00291 SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName); \ 00292 RetType FuncName() const { \ 00293 SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(); \ 00294 } \ 00295 SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName) 00296 00297 #define SimTK_PLUGIN_DEFINE_FUNCTION1(RetType, FuncName, Arg1) \ 00298 typedef RetType (*FuncName##__Type__)(Arg1); \ 00299 SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName); \ 00300 RetType FuncName(Arg1 a1) const { \ 00301 SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(a1); \ 00302 } \ 00303 SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName) 00304 00305 #define SimTK_PLUGIN_DEFINE_FUNCTION2(RetType, FuncName, Arg1, Arg2) \ 00306 typedef RetType (*FuncName##__Type__)(Arg1,Arg2); \ 00307 SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName); \ 00308 RetType FuncName(Arg1 a1, Arg2 a2) const { \ 00309 SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(a1,a2); \ 00310 } \ 00311 SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName) 00312 00313 00314 } // namespace SimTK 00315 00316 #endif // SimTK_SimTKCOMMON_PLUGIN_H_ 00317 00318