Download the source code

A plug-in is a software component to extent the functionality of an application. A Media player is a typical example of applications which make use of the plug-in architecture. All most all Media Players available now uses plug-in modal to deal with different input file formats and output device. Winamp, a popular media player, heavily uses plugging for input, output, visualization, DSP, etc… This is same in the case of Microsoft Media Player also.

As I already stated, a plug-in is a software component to extent an application. In Microsoft Windows, a plug-in is normally a DLL or a COM component. An application which consumes or uses the plug-in is called plug-in host. The host application loads the plug-in at start or when it is really needed to load the plug-in. Typically the host application scans a particular folder for the plug-in and loads all Plug-ins or it looks a number of predefined folders which is specified is a configuration file of registry. The host application collects the details of all the Plug-ins and gives the user the freedom to choose which plug-in to use or automatically choose the plug-in to use according to the user input. For example in case of media players, the user can choose which visualization plug-in should be active at a time. In case of which file to play, the host determine which plug-in to use as per the user’s selection.

The host application uses a well defined protocol to communicate with the plug-in. The protocol defines which functions we have to export in case the plug-in is a DLL or which interface we have to implement in case of a COM component. The host can make use of any component which confirms this protocol. So the host does not depend on a particular plug-in but all Plug-ins depends on the host.

The sample application presented here is a simple Image Viewer application. It will display three different image files, JPEG and PNG files. For JPEG and PNG images we use LIGJPEG and LIBPNG external libraries since these are very complex formats. Our Plug-ins will be simple DLL files. The host will load these DLL files and communicate with them as per the defined protocol. The format of the JPG and PNG files are complex and out of the scope of this article.

Now the communication protocol has to be defined. We have only one type of plug-in: input plug-in, whenever we need to read data from the file we use these plug-in. We can define the functions to be exported as:

IInputPlugin* GetPluginInterface();

This is the only function that needs to be exported. This function returns a pointer to the IInputPlugin. The IInputPlugin is defined as


class CInputPlugin
{
public:
virtual const char* GetFileName() = 0;
virtual const char* GetPluginName() = 0;
virtual const char* GetDescription() = 0;
virtual unsigned long GetVersion() = 0;
virtual const char* GetFilterString() = 0;
virtual const char* GetExtension() = 0;
virtual DWORD GetWidth() = 0;
virtual DWORD GetHeight() = 0;
virtual BYTE GetBitCount() = 0;
virtual BYTE GetColorType() = 0;
virtual BYTE GetPlanes() = 0;
virtual BYTE GetCompression() = 0;
virtual DWORD GetScanLineWidth() = 0;
virtual DWORD GetPasses() = 0;
virtual int OpenImage(const char* lpszFile) = 0;
virtual int ReadScanLine(unsigned char* lpBuffer,unsigned long dwSize,unsigned int uLine) = 0;
virtual int CloseImage() = 0;
virtual void Release() = 0;
};

typedef CInputPlugin IInputPlugin;

As you can see the IInputPlugin is an ABC(Abstract Base class). The input plug-in needs to implement this interface and return the pointer to the implementation class. The host application will use this pointer to manipulate he image

The host application is a normal MFC application. When the application loads it scans a folder for plug-in DLLs and loads all the Plug-ins found. The host application stores all the information about the plug-in for future use. When the user opens an image file, the host application searches this information to find which plug-in to use. The host then loads the corresponding plug-in and calls the OpenImage function. If the function returns 1, the get the information about the image and create a DIB Section based on the information. Then the host reads all the scan lines and displays the image.

There are many ways to extend this application. One way is to implement output Plug-ins. The output Plug-ins converts the given image data to some other formats and saves this to a file. We can define the protocol just like the input Plug-ins and create different output Plug-ins. This will give the user the ability to convert from one image format to another. One another way is to support image processing Plug-ins. The image processing Plug-ins accepts the image data and processes it and gives the processed image back to the host. There are many possibilities; I left this to your imagination.

Although I use C++/MFC to create this, we can extend this to any other languages or platforms. Plug-in Architecture is very powerful and using this we can create easily extensible application.

This is a very simple introduction, to better understand this architecture just search for Plug-in Architecture; you will find a lot of information.

The sample application is only tested in Windows 2003.