COM: Creating a COM Component using C++ (Part-2)

This is the series of articles explaining creating a COM component using C++. In our previous article, we have defined an interface IHello and compiled the IDL file using Microsoft’s MIDL compiler.

Now we are going to define a COM Component using C++. Remember that the all the interfaces defined in an IDL file must be implemented.

Step (1). Derive a C++ class from IHello interface. Add necessary header files.

// HelloComponent.h
//
#include "Hello.h"
#include "Hello_i.c"

class CHelloComponent : public IHello
{
};

Step (2). Declare the class methods in .h file and implement those methods in .cpp file for maintainability. Add IHello and IUnknown interface method declarations into CHelloComponent class. IUnknown methods maintain object’s reference counting; to keep object reference count add a variable (for eg: m_cRef).

// HelloComponent.h
//
#include "Hello.h"
#include "Hello_i.c"

#include <iostream>

class CHelloComponent : public IHello
{
public:
	CHelloComponent() : m_cRef (1)
	{
	}
	~CHelloComponent()
	{
	}

	// -- IUnknown Methods
	ULONG STDMETHODCALLTYPE AddRef();
	ULONG STDMETHODCALLTYPE Release();
	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv);

	// -- IHello Method
	HRESULT STDMETHODCALLTYPE SayHello(BSTR message);

private:
	ULONG m_cRef;
};

Step (3). Lets implement the IUnknown methods first. AddRef and Release methods of IUnknown interface maintains the object’s reference counting to ensure the lifetime of the object. Once no reference are there for the object; object will be released from the memory. These things are not done automatically; we need to implement this functionality in AddRef and Release methods. These are the guidelines for IUnknown interface. Because this is an interface, implementation doesn’t exist itself. But whoever going to implement IUnknown interface, they should implement these methods.

ULONG CHelloComponent::AddRef()
{
	return (++m_cRef);
}

ULONG CHelloComponent::Release()
{
	if ( --m_cRef != 0 ) 
		return m_cRef; 

	delete this;
	return 0;
}

AddRef will increment and Release will decrement the reference count value by 1. Release method also releases the object from memory when the reference count is 0. This way we have achieved initial goal of IUnknown interface.

Step (4). Another important method of IUnknown interface is QueryInterface. This method retrieves the requested interface pointer to the callers. A component can implement multiple interfaces. This function should always return the appropriate interface pointer requested by the caller.

HRESULT CHelloComponent::QueryInterface(REFIID riid, LPVOID *ppv)
{
	if ( ( riid == IID_IHello ) || ( riid == IID_IUnknown ) )
	{
		*ppv = (void *) this;
		AddRef(); // -- Maintain the reference count
	}
	else
		*ppv = NULL;

	return (*ppv == NULL) ? E_NOINTERFACE : S_OK;
}

In this component IHello and IUnknown interfaces are implemented. If the requested interface pointer is either of this type, QueryInterface function will return the pointer to this component. Otherwise this returns, NULL pointer with E_NOINTERFACE return code.

Step (5). Now we have to implement IHello‘s SayHello method. This method simply takes a string as an argument and display the string on the console window.

HRESULT CHelloComponent::SayHello(BSTR message)
{
	_bstr_t bstrMessage = message;

	cout << bstrMessage << endl;

	return S_OK;
}

_bstr_t class is the helper class deals with BSTR data types. It internally maintains resource allocation and deallocation for BSTR data types or you can specify it through its parameter.

Step (6). Include the necessary files in HelloComponent.cpp file.

#include "HelloComponent.h"

// -- for _bstr_t
#include <comutil.h>

// -- for std namespace; for cout etc.,
using namespace std;

Step (7). Now compile HelloComponent.cpp from command prompt using Microsoft’s tool cl.exe.

cl HelloComponent.cpp /EHsc /c

The file HelloComponent.cpp will compile and it will generate an .obj file.

Now the HelloComponent is ready. But, this is not enough to deploy the component. We need to wrap the component into a DLL and register it into Windows registry to complete the deployment. We will discuss about these in our next articles.

**

1 comment for “COM: Creating a COM Component using C++ (Part-2)

Leave a Reply