Simbody  3.4 (development)
Plugin.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines