Simbody  3.5
Plugin.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_PLUGIN_H_
2 #define SimTK_SimTKCOMMON_PLUGIN_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2009-12 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
34 #include <string>
35 #include <stdexcept>
36 
37 namespace SimTK {
38 
97 public:
98  explicit Plugin(const std::string& defaultPathname="");
99  ~Plugin(); // unloads the plugin if it was loaded
100 
114  bool load(const std::string& name="");
115 
120  void unload();
121 
124  bool isLoaded() const {return m_handle != 0;}
125 
126  const std::string& getLoadedPathname() const {
127  return m_loadedPathname; // empty if nothing loaded
128  }
129 
132  std::string getLastErrorMessage() const {return m_lastMessage;}
133 
139  void setSearchPath(const Array_<std::string>& pathIn) {
140  m_searchPath.clear();
141  for (unsigned i=0; i < pathIn.size(); ++i)
142  addSearchDirectory(pathIn[i]);
143  }
144 
145  const Array_<std::string>& getSearchPath() const {return m_searchPath;}
146 
150  void addSearchDirectory(const std::string& directory) {
151  const std::string absDir = Pathname::getAbsoluteDirectoryPathname(directory);
152  if (!absDir.empty())
153  m_searchPath.push_back(absDir);
154  }
155 
160  void prependSearchDirectory(const std::string& directory) {
161  const std::string absDir = Pathname::getAbsoluteDirectoryPathname(directory);
162  if (!absDir.empty())
163  m_searchPath.insert(m_searchPath.begin(), absDir);
164  }
165 
166 
169  static void* loadPluginByFileName(const std::string& name, std::string& errMsg);
174  static void* loadDebugOrReleasePlugin(const std::string& base, const std::string& extension,
175  std::string& loadedFileName, std::string& errMsg);
178  static void* getSymbolAddress(void* handle, const std::string& name, std::string& errMsg);
181  static void unloadPlugin(void* handle);
182 
224  static bool deconstructLibraryName( const std::string& name,
225  bool& isAbsolutePath,
226  std::string& directory,
227  std::string& libPrefix,
228  std::string& baseName,
229  std::string& debugSuffix,
230  std::string& extension);
231 
235  static std::string getDynamicLibPrefix();
236 
240  static std::string getDynamicLibExtension();
241 
246  static std::string getDynamicLibDebugSuffix();
247 
248 protected:
249  std::string m_defaultName; // if any
251 
252  std::string m_loadedPathname; // absolute
253  void* m_handle;
254  mutable std::string m_lastMessage;
255 
256 };
257 
258 
259 #define SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName) \
260  struct FuncName##__Holder__ { \
261  FuncName##__Holder__() : fp(0) {} \
262  bool loadSym(void* h, std::string& msg) const { \
263  if(!fp) fp =(FuncName##__Type__) \
264  Plugin::getSymbolAddress(h, #FuncName, msg); \
265  return (fp!=0); \
266  } \
267  mutable FuncName##__Type__ fp; \
268  } FuncName##__Ref__
269 #define SimTK_PLUGIN_XXX_MAKE_BODY(FuncName) \
270  if (!FuncName##__Ref__.loadSym(m_handle,m_lastMessage)) \
271  throw std::runtime_error \
272  ("Plugin function " #FuncName " not found: " + m_lastMessage); \
273  return FuncName##__Ref__.fp
274 #define SimTK_PLUGIN_XXX_MAKE_SYMTEST(Symbol) \
275  bool has_##Symbol() const { \
276  return Symbol##__Ref__.loadSym(m_handle,m_lastMessage); \
277  }
278 
279 #define SimTK_PLUGIN_DEFINE_SYMBOL(Type, SymName) \
280  typedef Type SymName##__Type__; \
281  SimTK_PLUGIN_XXX_MAKE_HOLDER(SymName); \
282  const Type& SymName() const { \
283  if (!SymName##__Ref__.loadSym(m_handle,m_lastMessage)) \
284  throw std::runtime_error \
285  ("Plugin symbol " #SymName " not found: " + m_lastMessage); \
286  return *(SymName##__Ref__.fp); \
287  }
288 
289 #define SimTK_PLUGIN_DEFINE_FUNCTION(RetType, FuncName) \
290  typedef RetType (*FuncName##__Type__)(); \
291  SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName); \
292  RetType FuncName() const { \
293  SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(); \
294  } \
295  SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName)
296 
297 #define SimTK_PLUGIN_DEFINE_FUNCTION1(RetType, FuncName, Arg1) \
298  typedef RetType (*FuncName##__Type__)(Arg1); \
299  SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName); \
300  RetType FuncName(Arg1 a1) const { \
301  SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(a1); \
302  } \
303  SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName)
304 
305 #define SimTK_PLUGIN_DEFINE_FUNCTION2(RetType, FuncName, Arg1, Arg2) \
306  typedef RetType (*FuncName##__Type__)(Arg1,Arg2); \
307  SimTK_PLUGIN_XXX_MAKE_HOLDER(FuncName); \
308  RetType FuncName(Arg1 a1, Arg2 a2) const { \
309  SimTK_PLUGIN_XXX_MAKE_BODY(FuncName)(a1,a2); \
310  } \
311  SimTK_PLUGIN_XXX_MAKE_SYMTEST(FuncName)
312 
313 
314 } // namespace SimTK
315 
316 #endif // SimTK_SimTKCOMMON_PLUGIN_H_
317 
318 
#define SimTK_SimTKCOMMON_EXPORT
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:218
Declaration of the SimTK::Pathname class providing platform-independent manipulation of file pathname...
void addSearchDirectory(const std::string &directory)
Add a directory to the end of the search path for this kind of plugin.
Definition: Plugin.h:150
static std::string getAbsoluteDirectoryPathname(const std::string &dirPathname)
This is the same as getAbsolutePathname() except that the final segment is interpreted as a directory...
Definition: Pathname.h:163
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
const Array_< std::string > & getSearchPath() const
Definition: Plugin.h:145
This file defines the Array_<T,X> class and related support classes including base classes ArrayViewC...
std::string getLastErrorMessage() const
If anything goes wrong the last error message is stored so you can retrieve it with this method...
Definition: Plugin.h:132
void * m_handle
Definition: Plugin.h:253
const std::string & getLoadedPathname() const
Definition: Plugin.h:126
std::string m_loadedPathname
Definition: Plugin.h:252
This is the base class for representing a runtime-linked dynamic library, also known as a "plugin"...
Definition: Plugin.h:96
std::string m_defaultName
Definition: Plugin.h:249
Mandatory first inclusion for any Simbody source or header file.
std::string m_lastMessage
Definition: Plugin.h:254
bool isLoaded() const
Is there currently a DLL associated with this Plugin object? If so you can call getLoadedPathname() t...
Definition: Plugin.h:124
void setSearchPath(const Array_< std::string > &pathIn)
Provide a list of directories in the order you want them searched to find a plugin that was provided ...
Definition: Plugin.h:139
void prependSearchDirectory(const std::string &directory)
Put a directory on the front of the search path for this kind of plugin.
Definition: Plugin.h:160
Array_< std::string > m_searchPath
Definition: Plugin.h:250