Simbody
Public Member Functions | Static Public Member Functions | Protected Attributes

SimTK::Plugin Class Reference

This is the base class for representing a runtime-linked dynamic library, also known as a "plugin", in a platform-independent manner. More...

#include <Plugin.h>

List of all members.

Public Member Functions

 Plugin (const std::string &defaultPathname="")
 ~Plugin ()
bool load (const std::string &name="")
 Attempt to load a plugin of the given name if any, otherwise the default name (if any).
void unload ()
 If a plugin is loaded, unload it now otherwise do nothing.
bool isLoaded () const
 Is there currently a DLL associated with this Plugin object? If so you can call getLoadedPathname() to find out which one.
const std::string & getLoadedPathname () const
std::string getLastErrorMessage () const
 If anything goes wrong the last error message is stored so you can retrieve it with this method.
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 as a relative path name.
const Array_< std::string > & getSearchPath () const
void addSearchDirectory (const std::string &directory)
 Add a directory to the end of the search path for this kind of plugin.
void prependSearchDirectory (const std::string &directory)
 Put a directory on the front of the search path for this kind of plugin.

Static Public Member Functions

static void * loadPluginByFileName (const std::string &name, std::string &errMsg)
 If this fails the return value will be null and the system's human-readable error message is in errMsg.
static void * loadDebugOrReleasePlugin (const std::string &base, const std::string &extension, std::string &loadedFileName, std::string &errMsg)
 If we're in Debug mode then this method attempts first to load the Debug version of the indicated library which it constructs as base+"_d"+extension.
static void * getSymbolAddress (void *handle, const std::string &name, std::string &errMsg)
 If this fails the return value will be null and the system's human-readable error message is in errMsg.
static void unloadPlugin (void *handle)
 Given a handle returned by loadPluginByFileName(), unload the plugin.
static bool deconstructLibraryName (const std::string &name, bool &isAbsolutePath, std::string &directory, std::string &libPrefix, std::string &baseName, std::string &debugSuffix, std::string &extension)
 Dismantle a supplied library's file or pathname into its component parts.
static std::string getDynamicLibPrefix ()
 This is the platform dependent string which gets prepended to a dynamic library baseName to form the fileName -- "lib" on Unix-based systems and "" (empty string) for Windows.
static std::string getDynamicLibExtension ()
 This is the platform dependent extension (including the ".") used by default to identify dynamically linked libraries -- ".so" on Linux, ".dylib" on Apple, and ".dll" on Windows.
static std::string getDynamicLibDebugSuffix ()
 Obtain the appropriate debug suffix to use.

Protected Attributes

std::string m_defaultName
Array_< std::string > m_searchPath
std::string m_loadedPathname
void * m_handle
std::string m_lastMessage

Detailed Description

This is the base class for representing a runtime-linked dynamic library, also known as a "plugin", in a platform-independent manner.

For any particular kind of plugin, derive a concrete class from this one and use the macros to describe the functions or data you expect to find there. Then each plugin library you load of that type is an object of the concrete class you defined. The derived class constructor sets the search policy for plugin libraries of that type. For example:

 class MyPlugin : public Plugin {
 public:
     explicit MyPlugin() : Plugin() {
         addSearchDirectory(Pathname::getInstallDir("SimTK_INSTALL_DIR", "SimTK") 
                             + "/lib/plugins/");
     }
     SimTK_PLUGIN_DEFINE_FUNCTION1(int,exportedFunctionWithOneArg,const std::string&);
     SimTK_PLUGIN_DEFINE_FUNCTION(SomeObjectType*,anExportedFunctionNoArgs);
     SimTK_PLUGIN_DEFINE_FUNCTION(void, someFunction);
     SimTK_PLUGIN_DEFINE_SYMBOL(SymbolType, nameOfExportedSymbol);
 };
 

Then this class is used as follows:

     MyPlugin lib1;
     if (!lib1.load("libraryName")) {
         std::cerr << lib1.getLastErrorMessage() << std::endl;
         // exit, retry or whatever
     }
     // At this point you can call the functions and access
     // the symbols, e.g.
     int i = lib1.exportedFunctionWithOneArg("hi");
 

The currently available macros are:

These define methods in the derived class which can obtain the symbol address from the plugin library as needed. The methods will have the same signature as the library's exported function. In the case of the symbol, a no-argument method named the same as the symbol will be created. For example,

 SimTK_PLUGIN_DEFINE_SYMBOL(int, myCounter); 

says the library contains an exported external symbol of type int named "myCounter". If the Plugin object is "plugin" then you can access this symbol (read only) as

 const int& counter = plugin.myCounter(); 

The macros also define another method of the same name as the symbol or function, but prepended with "has_". This returns true if the named object is exported by the library, otherwise false. If you try to access a method or symbol without checking first, an exception will be thrown if the library doesn't export the symbol.


Constructor & Destructor Documentation

SimTK::Plugin::Plugin ( const std::string &  defaultPathname = "") [explicit]
SimTK::Plugin::~Plugin ( )

Member Function Documentation

bool SimTK::Plugin::load ( const std::string &  name = "")

Attempt to load a plugin of the given name if any, otherwise the default name (if any).

If the name is relative it will be subject to the search rule associated with this Plugin object. In any case the filename will be deconstructed to find the library baseName to which we will add the "lib" prefix if necessary, the "_d" suffix if appropriate, and the platform-specific suffix.

load() returns true if it succeeds, otherwise you can call getLastErrorMessage() to find out what's wrong. If a library is already loaded, this returns false without checking to see whether you are trying to reload the same library. Call isLoaded() to check whether a plugin has already been loaded, getLoadedPathname() to get a canonicalized absolute pathname for the loaded library.

void SimTK::Plugin::unload ( )

If a plugin is loaded, unload it now otherwise do nothing.

Note that whether the corresponding DLL is actually unloaded from the address space is up to the operating system, however, this Plugin object will be disassociated from it regardless.

bool SimTK::Plugin::isLoaded ( ) const [inline]

Is there currently a DLL associated with this Plugin object? If so you can call getLoadedPathname() to find out which one.

const std::string& SimTK::Plugin::getLoadedPathname ( ) const [inline]
std::string SimTK::Plugin::getLastErrorMessage ( ) const [inline]

If anything goes wrong the last error message is stored so you can retrieve it with this method.

void SimTK::Plugin::setSearchPath ( const Array_< std::string > &  pathIn) [inline]

Provide a list of directories in the order you want them searched to find a plugin that was provided as a relative path name.

This is ignored if an absolute path name is given. Each of the directory names will be immediately expanded to an absolute path name if it isn't already.

const Array_<std::string>& SimTK::Plugin::getSearchPath ( ) const [inline]
void SimTK::Plugin::addSearchDirectory ( const std::string &  directory) [inline]

Add a directory to the end of the search path for this kind of plugin.

This will be expanded immediately to an absolute path name if it isn't already. If the directory is blank it is ignored.

void SimTK::Plugin::prependSearchDirectory ( const std::string &  directory) [inline]

Put a directory on the front of the search path for this kind of plugin.

This will be expanded immediately to an absolute path name if it isn't already. If the directory name is blank it is ignored.

static void* SimTK::Plugin::loadPluginByFileName ( const std::string &  name,
std::string &  errMsg 
) [static]

If this fails the return value will be null and the system's human-readable error message is in errMsg.

static void* SimTK::Plugin::loadDebugOrReleasePlugin ( const std::string &  base,
const std::string &  extension,
std::string &  loadedFileName,
std::string &  errMsg 
) [static]

If we're in Debug mode then this method attempts first to load the Debug version of the indicated library which it constructs as base+"_d"+extension.

If that fails (or if we're not in Debug mode) it will try to load the Release version (base+extension) instead.

static void* SimTK::Plugin::getSymbolAddress ( void *  handle,
const std::string &  name,
std::string &  errMsg 
) [static]

If this fails the return value will be null and the system's human-readable error message is in errMsg.

static void SimTK::Plugin::unloadPlugin ( void *  handle) [static]

Given a handle returned by loadPluginByFileName(), unload the plugin.

Nothing happens until the last reference is unloaded.

static bool SimTK::Plugin::deconstructLibraryName ( const std::string &  name,
bool &  isAbsolutePath,
std::string &  directory,
std::string &  libPrefix,
std::string &  baseName,
std::string &  debugSuffix,
std::string &  extension 
) [static]

Dismantle a supplied library's file or pathname into its component parts.

This can take pathnames like

   
            /usr/local/libMyDll_d.so
            e:\Program Files\Something\myLibrary_d.dll
        

and chop them into

        directory                       libPrefix baseName    debug extension
        ------------------------------- --------- ----------- ----- ---------
        /usr/local/                     lib       MyDll         _d    .so 
        e:\Program Files\Something\     (none)    myLibrary     _d    .dll
        

as well as tell you whether the given pathname is absolute or relative (and thus subject to search rules). At the beginning of the pathname (or right after the drive specification on Windows) we recognize three special symbols:

  • "/" means root; i.e., this is an absolute path name starting from the root directory (this drive's root for Windows).
  • "." starts an absolute path name which is relative to the current working directory (or drive's cwd on Windows).
  • "@" starts an absolute path name which is relative to the directory in which the currently running executable is located.

Anywhere in the pathname, the name ".." means "go up one level from the prior directory". ".." at the start is interpreted as "./..". A '.' appearing anywhere in the path name except the begining is ignored. An '@' appearing anywhere in the pathname other than the beginning is treated as an ordinary file character.

The pathname components are returned as separate strings with separators included such that concatenating all the strings reproduces the pathname in a canonicalized form. The "drive" letter prefix is recognized only when running on Windows; otherwise a prefix like "C:" is treated as ordinary file name characters. Note that we include the drive letter as part of the absolute directory. White space is removed, and path separator characters in the directory are changed to the appropriate slash for the currently running platform (i.e. backslash for Windows and forward slash everywhere else). The return value is false if the input path name is ill-formed; in that case it still tries to parse as much as it can.

static std::string SimTK::Plugin::getDynamicLibPrefix ( ) [static]

This is the platform dependent string which gets prepended to a dynamic library baseName to form the fileName -- "lib" on Unix-based systems and "" (empty string) for Windows.

static std::string SimTK::Plugin::getDynamicLibExtension ( ) [static]

This is the platform dependent extension (including the ".") used by default to identify dynamically linked libraries -- ".so" on Linux, ".dylib" on Apple, and ".dll" on Windows.

static std::string SimTK::Plugin::getDynamicLibDebugSuffix ( ) [static]

Obtain the appropriate debug suffix to use.

This is not platform dependent but rather depends on whether this compilation unit was built in Debug or Release modes. If Debug, then the string "_d" is returned, otherwise the empty string.


Member Data Documentation

std::string SimTK::Plugin::m_defaultName [protected]
Array_<std::string> SimTK::Plugin::m_searchPath [protected]
std::string SimTK::Plugin::m_loadedPathname [protected]
void* SimTK::Plugin::m_handle [protected]
std::string SimTK::Plugin::m_lastMessage [mutable, protected]

The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines