Adding Plug-ins To Your Application
by (23 November 2002)
|Return to The Archives
Letís get this out of the way; the "who should read this" part. I wrote this article in hopes that the reader would be proficient in C++ and know about inheritance, virtual functions and pure virtual functions. If you are not then Iíd highly suggest looking it up. Search engines such as Google are great for just that. Ok now that thatís out of the way letís move on!
For my Final Project at Full Sail I was in charge of writing a 3d engine for our game Dodge Ball (a remake of the classic NES game Super Dodge Ball). The engine didnít need to be too complex; it needed a basic scene graph, model loading, character animation, and be able to support multiple rendering APIs. Now the first three tasks, while not simple, are fairly straight forward on how we were going to implement them, but the last task of reaching API independence was not. But like any good programmer I did my homework and decided that a plug-in architecture was just what we needed in the Dodge Ball engine. This is also a good time to note that API independence is not the only good reason for using plug-ins in your application; the possibilities for its use are endless.
One key feature to an Object Oriented Plug-in system is the abstract interface. If youíre already familiar with abstract interfaces then you can skip this part and go right to the next section. An abstract interface is a generic framework for which all other classes that are derived from will work. Here is an example of an abstract interface:
Notice that all the member functions of this structure are pure virtual. This means that it cannot be its own instance without a base class that overrides them. So how is this useful? Well letís take a look at the following two classes that use this same interface, but do completely different things.
Now the fruits of our labor are upon us! We can make a pointer to the base class (this works because there is no instance of the base class) and choose at run time what output we want. So letís see how we can do this:
This program randomly selects what output method to use and prints 10 versions of ďAbstract Interfaces are cool!Ē Well thatís about it for abstract interfaces, if you have any questions feel free to email me at firstname.lastname@example.org.
Dynamic Link Libraries (DLLs)
If youíre going to be using a plug-in architecture in your next application, and I suggest you do, then youíll probably be using DLLs. DLLs, or dynamic link libraries, work just like regular libraries but are loaded at run time and are compiled into their own components, not into the executable. Now there are two flavors of DLLs. You can use a DLL just like a regular library and link to it the same way you would Direct X or Open GL or you could link it up when you run the program. Let me tell you the first one is the easiest way, but will not work for our needs. We want to choose what plug-in to use when we start the program not when we compile it, hell we can even have the user choose what plug-in to use, thatís the beauty of plug-ins. So letís go on to how weíre going to do this.
To load a plug-in, we need a plug-in, so letís create one now. What you need to do is create either a dll project (msvc) or a make file (gcc) and add in one of derived classes that we wrote before. To be able to access this class from outside the DLL weíre going to have to make a function to do it for us. So here it is:
This function can be placed in the same cpp file as the CConsole class. Well this seems kind of cool, but itís not enough, we need to tell the compiler that we intend to let outside sources use this function. So what we need to do is export it like so.
Ahh yes, that should be enough for getting an instance to the class. Now we need to move on to the next portion of this tutorial, how to link to the library and use this class.
Itís very simple to load up a DLL and get the function we want to use, as long as we follow the 5 easy steps that is.
Step 1: Load the library
Loading the library is easy with the Win32 functions :D All we need to do is have the name of the DLL to load. The syntax is as follows:
Step 2: Get our export function
Now that the library is loaded we can now try and get a function that we know should exist inside it. This is the export function we wrote earlier.
This might seem a little tricky, but itís very simple once you know what is going on. pfnLoad is a pointer to our export function that GetProcAddress returns.
Step 3: Get our class from the plugin
So with our new found power, or better known as a function pointer to our export function, we can now get an instance to some sort of text output derived class.
Step 4: Use the plug-in all we friggin want!
Step 5: Clean up our act.
Letís tell windows that we donít want this DLL anymore so please unload it for us.
For Those That Caught it
You might have noticed that this produces a memory leak because weíre not freeing up the memory new-ed in the export function. Well Iím going to steal something from Microsoftís COM right now and add in a function to our abstract interface.
What this function will do is force all the derived objects to delete itself from memory. How is this done? Well letís add it into the CConsole class
You have to be very careful when doing this and make sure that youíre only calling the release function when it was created via new, otherwise youíre in for a world of access violation pain. So now I should probably fix step five and make everything right.
The New Step 5:
I Really Only Want to Write This Once
After this long tutorial, youíre probably wondering if itís worth it at all to use plug-ins. Well if a plug-in architecture is implemented correctly you really only have to write one class for all plug-ins. Yes one class. Here is the plug-in loading class I wrote for the Dodge Ball engine:
Well I hope you enjoyed reading this tutorial as much as I enjoyed writing it. Iím really happy to be able to give something back to the community. If you have any questions, comments (good or bad), concerns, or just want to chat about game development feel free to email me at email@example.com
About the author: Garret Foster is a recent graduate from Full Sail. He likes spending most if his newly found time working on his next project and brushing up on all the games he missed while getting his education. He can be contacted through his web site, at www.garretfoster.com.