plugin.h File Reference
Simplify 'plugin' classes to be discovered and/or loaded at runtime. More...
#include <openbabel/babelconfig.h>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <sstream>
#include <cstring>

Go to the source code of this file.
Namespaces | |
namespace | OpenBabel |
Classes | |
struct | CharPtrLess |
Case insensitive string comparison for PluginMapType key. More... | |
class | OBPlugin |
Base class for all types of dynamic classes discovered at runtime. More... | |
Defines | |
#define | MAKE_PLUGIN(BaseClass) |
Detailed Description
Simplify 'plugin' classes to be discovered and/or loaded at runtime.The code in this file makes it easy to make 'plugin' classes. These classes are derived from a base class, like OBFingerprint. The derived classes ('sub-types' like fingerprint2) usually have a single instance. Plugin classes are only discovered at runtime, so no existing code needs to be changed when adding a new derived class. In some builds the new code can be added or removed by just moving a DLL or so file. The plugin classes derived from any base class (including new ones) type can be listed from the commandline.
Step-by-Step Instructions
1) In the header file for YourBaseClass (which handles whatsits). Make sure to include the plugin.h header , derive the class from OBPlugin and in its definition add the MAKE_PLUGIN macro and a function TypeID() containing a simple descriptor of the type
#include <openbabel/plugin.h> class YourBaseClass : public OBPlugin { MAKE_PLUGIN(YourBaseClass) const char* TypeID() { return "whatsits"; }; ...rest of implementation, probably involving virtual functions redefined in the sub-type classes };
2) Declare each sub-type in a class derived from the base class and give it a constructor which calls OBPlugin constructor as shown:
class YourSubType1 : public YourBaseClass { public: YourSubtype1(const char* ID, bool IsDefault=false) : YourBaseClass(ID, IsDefault){} virtual string Description() { return "A description with one or more lines";}; ...rest of implementation };
3) Declare a global instance of the sub-type class which specifies its ID. and, optionally, whether it is to be regarded as the default type of YourBaseClass.
YourSubType1 theType1("whatsit2",true);
4) The following functions are available:
YourBaseClass* YourBaseClass::FindType(const char* ID); This returns the default type when ID is NULL or empty.
To list the sub-types of any plugin class use the List which sends to cout by default (or any other ostream if specified).
OBPlugin::List("whatsits")
It is also possible to iterate through each sub-type by the following code:
OBPlugin::PluginIterator itr; for(itr=OBPlugin::Begin("whatsits");itr!=OBPlugin::End("whatsits");++itr) { itr is a std::map::const_iterator itr->first is the ID of the subtype; itr->second is The OBPlugin* which you will have to cast to your type }
YourBaseClass* MakeNewInstance();
How it works
MAKE_PLUGIN(YourBaseClass) inserts the following code into YourBaseClass:
protected: //The collection of sub-types is in a local static variable to avoid //any difficulties with the order of initialization of static objects. static PluginMapType& Map() { static PluginMapType m; return m; } //Making the map accessible to the base class (Cannot be used during construction) virtual PluginMapType& GetMap()const { return Map(); } public: static YourBaseClass*& Default() { static YourBaseClass* d; return d; } //Constructor registers the sub-type YourBaseClass(const char* ID, bool IsDefault=false) { _id = ID; if(ID && *ID) //do not register if ID is empty { if(IsDefault || Map().empty()) Default() = this; Map()[ID]=this; //Ensure YourBaseClass is registered in OBPlugin so it can be accessed from the commandline PluginMap()[TypeID()] =this; } } static YourBaseClass* FindType(const char* ID) { if(!ID || *ID==0) return Default(); return static_cast<YourBaseClass*>(BaseFindType(Map(),ID)); }
Define Documentation
#define MAKE_PLUGIN | ( | BaseClass | ) |
Value:
protected:\ virtual PluginMapType& GetMap()const{return Map();}\ static PluginMapType& Map(){static PluginMapType m;return m;}\ public:\ static BaseClass*& Default(){static BaseClass* d;return d;}\ BaseClass(const char* ID, bool IsDefault=false)\ {_id=ID;if(ID&&*ID){if(IsDefault || Map().empty()) Default() = this;\ Map()[ID]=this;PluginMap()[TypeID()] =this;}}\ static BaseClass* FindType(const char* ID)\ {if(!ID || *ID==0) return Default();\ return static_cast<BaseClass*>(BaseFindType(Map(),ID));}