This is the base class for representing a runtime-linked dynamic library, also known as a "plugin", in a platform-independent manner.
More...
|
| 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). More...
|
|
void | unload () |
| If a plugin is loaded, unload it now otherwise do nothing. More...
|
|
bool | isLoaded () const |
| Is there currently a DLL associated with this Plugin object? If so you can call getLoadedPathname() to find out which one. More...
|
|
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. More...
|
|
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. More...
|
|
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. More...
|
|
void | prependSearchDirectory (const std::string &directory) |
| Put a directory on the front of the search path for this kind of plugin. More...
|
|
|
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. More...
|
|
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. More...
|
|
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. More...
|
|
static void | unloadPlugin (void *handle) |
| Given a handle returned by loadPluginByFileName(), unload the plugin. More...
|
|
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. More...
|
|
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. More...
|
|
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. More...
|
|
static std::string | getDynamicLibDebugSuffix () |
| Obtain the appropriate debug suffix to use. More...
|
|
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")
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.
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 beginning 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.