Introduction to Plug-in Architecture

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
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.

Introduction to OpenMP using Visual C++ 2005

OpenMP is an application programming interface (API) for shared memory multiprocessing programming on multiprocessor/multicore systems. OpenMP consists of a set of compiler directives and a set of support functions. OpenMP works in conjunction with Fortran, C and C++. It is tailored for Shared Memory environments. The Shared Memory model is an abstraction of centralized multiprocessor system consisting of a collection of processors with access to the same shared memory. Processors can interact and synchronize with each other through shared variables.

In shared memory model, the standard model of parallelism is Fork/Join parallelism. In Fork/Join parallelism, there will be only one thread is active at the start and end and is which is called master thread. Master thread executes the sequential portion and at some points where the parallelism is needed, master thread forks (creates or awakens) additional threads. The master thread and child threads executes in parallel through the parallel sections. At the end the created threads die or are suspended. The flow of controls returns to the master threads.

In OpenMP, the directives are expressed as pragmas (pragmatic informations). Following are the compiler directives & functions:

    parallel which preceeds a block to be executed in parallel
    for which preceeds a for block to be executed in parallel
    sections which preceeds section of blocks to be executed in parallel
    critical which preceeds critical section
    single which preceeds block of code that is to be executed by a single thread
      omp_get_num_procs() which returns the number of processors
      omp_get_num_threads() which returns the number of threads
      omp_get_thread_num() which returns the number of thread within group of threads
      omp_set_num_threads() which sets the number of threads for the parallel region

    Visual Studio Professional and above supports OpenMP. The Following program demonstrates a very simple use of OpenMP in Visual C++ 2005.
    #define _USE_MATH_DEFINES // for math defines in math.h


    #define ANGLE_MAX 360

    void main(int argc, char* argv[])
    int nDegree = 0;
    double dSins[ANGLE_MAX];

    #pragma omp parallel for
    for(nDegree=0; nDegree
    In order to compile it properly you have the use the /openmp compiler switch. You can set it from Project Properties->Configuration Properties->C/C++->Language:

    Ompoptions 150x150

    For a detailed list of OpenMP directives and support function please refer to this MSDN Documentation. In next few days I will try to update this post with more examples.