Interface and Wrappers

COM/DCOM is based on interfaces. Interfaces are standard protocol on which server and client exchange data parameters. These interfaces are written in Interface definition language. C++ compiler generates the raw C++ abstract class from this interface.

	[
		object,
		uuid(26AA3AE9-D24D-4881-9972-4B42B6B4A9B0),
		dual,
		helpstring("ICalculate Interface tiny calculator demo opject"),
		pointer_default(unique)
	]
	interface ICalculate : IDispatch
	{
		[propget, id(1), helpstring("Operand1 of calculator")]
		HRESULT Operand1([out, retval] long *pVal);
		
		[propput, id(1), helpstring("Operand1 of calculator")]
		HRESULT Operand1([in] long newVal);
		
		[propget, id(2), helpstring("Operand2 of calculator")]
		HRESULT Operand2([out, retval] long *pVal);
		
		[propput, id(2), helpstring("Operand2 of calculator")]
		HRESULT Operand2([in] long newVal);
		
		[id(3), helpstring("calculator main Operation method")]
		HRESULT DoOperation([in] char operation);
		
		[propget, id(4), helpstring("Result of calculator")]
		HRESULT Result([out, retval] long *pVal);
	};

Interface in C++ abstract class

MIDL compiler will generate the C++ raw interface from IDL file. Now server developer inherits this class in a wrapper and implements its background functionalities. While client also inherits this class and wraps it in C++ class. Client has to call raw virtual interfaces with arguments and has to process the output and deal with the error codes.

class ICalculate : public IDispatch
{
  public:
    virtual HRESULT __stdcall get_Operand1 (long * pVal ) = 0;
    virtual HRESULT __stdcall put_Operand1 (long pVal ) = 0;
    virtual HRESULT __stdcall get_Operand2 (long * pVal ) = 0;
    virtual HRESULT __stdcall put_Operand2 (long pVal ) = 0;
    virtual HRESULT __stdcall raw_DoOperation (char operation ) = 0;
    virtual HRESULT __stdcall get_Result (long * pVal ) = 0;
};

C++ wrapper class

This abstract class is used in both COM server and COM client applications. COM server wrapper should inherit it and should implement all the functions.

class CCalculateServer : public ICalculate
{
virtual HRESULT get_Operand1(long *pVal)
{
	*pVal = Op1;
	return S_OK;
}

virtual HRESULT put_Operand1(long newVal)
{
	Op1 = newVal;

	return S_OK;
}

virtual HRESULT get_Operand2(long *pVal)
{
	*pVal = Op2;

	return S_OK;
}

virtual HRESULT put_Operand2(long newVal)
{
	Op2 = newVal;

	return S_OK;
}

virtual HRESULT DoOperation(unsigned char operation)
{

	switch(operation){
	case '+':
		Result = Op1 + Op2;
		break;
	case '-':
		Result = Op1 - Op2;
		break;
	case '*':
		Result = Op1 * Op2;
		break;
	case '/':
		Result = Op1 / Op2;
		break;
	default:
		;
}
return S_OK;
}

virtual HRESULT get_Result(long *pVal)
{
	*pVal = Result;
	return S_OK;
}
};

Client wrapper should have a pointer of this interface inside the wrapper class. Client can call CreateInstance/QueryInterface to get an object instance from the server. Now client calls the raw interfaces from the wrapped functions. Client can validate input arguments, process output arguments and handle error codes.

class CCalculateClient 
{
private:
  ICalculate m_pCalculate;
public:
  HRESULT CreateInstance()
  {
	  m_pCalculate = NULL;
	  HRESULT hr;
	  hr = CoCreateInstance(CLSID_Calculate, 
	  NULL, CLSCTX_INPROC_SERVER,
	  IID_ICalculate,
     reinterpret_cast(&m_pCalculate));
	 return hr;
	  
  }
long GetOperand1 ( ) {
    long _result;
    HRESULT _hr = m_pCalculate->get_Operand1(&_result);
    if (FAILED(_hr)) throw _hr;
    return _result;
}

void SetOperand1 ( long pVal ) {
    HRESULT _hr = m_pCalculate->put_Operand1(pVal);
    if (FAILED(_hr)) throw _hr;
}

long GetOperand2 ( ) {
    long _result;
    HRESULT _hr = m_pCalculate->get_Operand2(&_result);
    if (FAILED(_hr)) throw _hr;
    return _result;
}

void SetOperand2 ( long pVal ) {
    HRESULT _hr = m_pCalculate->put_Operand2(pVal);
    if (FAILED(_hr)) throw _hr;
}

HRESULT DoOperation ( char operation ) {
    HRESULT _hr = m_pCalculate->raw_DoOperation(operation);
    if (FAILED(_hr)) throw _hr;
    return _hr;
}

long GetResult ( )
{
    long _result;
    HRESULT _hr = m_pCalculate->get_Result(&_result);
    if (FAILED(_hr)) throw hr;
    return _result;
}
};

About our authors: Team EQA

You have viewed 1 page out of 67. Your COM/DCOM learning is 0.00% complete. Login to check your learning progress.

#