#### Archived

This topic is now archived and is closed to further replies.

# ANWTH : Interface based plug-in systems Part 2

This topic is 5203 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, yesterday I brought you the first part of the ANWTH (Articles No-one Wanted To Have) series intitulated "Inteface based plug-in systems". If you have missed the yesterday part, you can find it here. In yesterdays part we talked about the basis you need to know when you want to dynamically load a DLL. wi-Z-art has added his knowledge by pointing out which changements have to be done when you are using an Unix based OS. Today I wanted to dig into the information structure and the interfaces needed for a plug in system. But during the writing of the article, I realised that it got to long if I did both. So I restricted this article to the information structure. If you have any suggestion to make or any problem to point out, don''t hesitate to reply in this thread. Here we go : 2. Identify a plug-in. Creating a plug-in based system means a lot of head ache to a lot of people. But once you have understood how a plug-in system works you''ll never want to be without one again. 2.1 The information structure. A very important component of the plug-in system is the way you recognize and create instances of the plug-ins. So, you need a way to easily recognize any plug-in that is embedded into a DLL. What is more easier than getting a pointer to a structure ? Since we want to have a more or less complete set of information about the plug-in, we''ll have to define a set of data which tells us exactly what we have there. 2.1.1 The Unique ID. One of the first elements we need is some kind of unique ID which identifies the module within your plug-in system. In most cases a GUID or UUID is used. But in our system this might be a little bit of overkill. I use an unsigned long to identify my modules. This gives me the possibility to have 429,4967,296 different modules. That should be enough. Well... I do a little restriction on that because I like to have a more or less clear (means readable) way to use my IDs. Therefor I have a little macro that helps me to stuff 4 chars into one unsigned long :
#define MAKESTRID(ch0, ch1, ch2, ch3)                       \
((ulong)(byte)(ch0) | ((ulong)(byte)(ch1) << 8) |   \
((ulong)(byte)(ch2) << 16) | ((ulong)(byte)(ch3) << 24 )) 
NOTE : ulong is my own abbreviation of unsigned long. To create an identifier I simply do :
ulong uMyID = MAKESTRID(''M'', ''y'', ''I'', ''D'');
uMyID then contains a value corresponding to the value I set by the MAKESTRID. 2.1.2 The type definition An important second entry in our information structure is the type of module we have loaded. This can but doesn''t have to be split into 2 parts : a major type and a sub type. A major type could be an animation system, a file system, a 2D module, a 3D module, etc. A minor type could be an animation controller, a cab file loader, a graphic file format or an 3d material. I like the idea of having a major and a sub type because that allows me quickly skip modules I don''t want. Basically this entries are enums like this :
enum PLUGIN_TYPE
{
PT_2D = 0,
PT_3D,
PT_Anim,
...
};

enum PLUGIN_SUBTYPE
{
PST_ANIM_CONTROL_QUAT_ROTATION,
...
} 
2.1.3 The code type. This can be a very important information, too. An entry that tells me of which type the DLL is : Retail or Debug. This would give the possibility to tell the system that handles the plug-in : "Ok, just hand me all retail compiled plug-ins" or "Give me the debug plug-ins only. I want to debug..." The code type itself can be an enum :
enum PLUGIN_CODETYPE
{
PT_CT_DEBUG = 0,
PT_CT_RELEASE,
PT_CT_UNKNOWN
}; 
2.1.4 The version number. This is very important. Your should stamp your plug-ins with a version number. Dependently on the version number one can decide wether or not to return a plug-in to the application. I personally only update the version number when I''m doing a changement in the interface of the plug-in I''ve created. Normally you''ll change it every time you rebuild your code and that is really how it should be. Since I''m working all alone I simply "forget" to do so (I know, I''m bad). A possible way to make sure that your plug-in is interface compatible is to have a major and a minor version number. The major version number (normally displayed before the dot) is only changed, when you modify the interface. The minor version number is changed, when you make a minor bug fix, tweak you application or add a new portion of code that does not change the interface. You can put the version number into one unsigned long by using the lower word for the minor version number and the higher word for the major version numer. Alternatively you can simply multiply your version number (which is a float) by 100 and cast it into an unsigned long. 2.1.5 Description strings. Since it is possible that you want to display some little information strings fo your plug-in, we''ll put them directly into the information structure. I usually have 4 entries here : The author, the plug-in name, a short and a long description. "Metron" "DDS format loader" "Loads the DirectX DDS format." "This module is part of the XY engine and is copyrighted by Metron" These are only some possible entries to the information structure. 2.1.6 Final structure. So, how does our final structure look like ? Here it is :
struct SPlugInDesc
{
ulong			uID;
PLUGIN_TYPE		uType;
PLUGIN_SUBTYPE	uSubType;
PLUGIN_CODETYPE uCodeType;

const char*		pAuthor;
const char*		pName;
const char*		pShortDesc;
const char*		pLongDesc;
ulong			uVersion;
}; 
This structure should help you to recognize your plug-in. I hope that there were some interesting things for you in here. The next part of this ANWTH lecture is given on monday since I have quite some stuff to do this week-end. Don''t forget : Reply to this thread if you have any suggestion or something to point out. Metron