Lesson 9 | Implementing COM objects |
Objective | Define a C++ implementation class using multiple inheritance. |
Implementing COM objects
In previous lessons we used C++ classes to define COM interfaces,
and looked at how to specify COM interfaces in IDL and the C++ class definitions created by compiling IDL files with MIDL.
Our next step is to study the standard development paradigms used to develop COM objects in C++. In practice, three standard mechanisms are used. They all define one C++ class to implement a COM object. They differ in how the object's interfaces are handled.
Several conventions have emerged for C++ implementations of COM objects.
These are using pointer member variables for each interface.
I. Creating COM objects using member pointers to interfaces
class CIMyComInterface : public IMyComInterface{
provide implementations of all pure
virtual methods in IMyComInterface
};
class CIYourComInterface : public IYourCominterface{
provide implementations of all pure
virtual methods in IYourComInterface
};
class CMyComObject{
CIMyComInterface *m_pim;
CIYourComInterface *m_piy;
…
};
The member pointers to each COM interface can be instantiated when the COM object is created or on demand when one of the interfaces is requested. The main advantage of this technique is that most developers are familiar with using member pointers to other classes.
Essential COM
II. Creating COM Objects with nested Classes
using nested classes, and usingmultiple inheritance.
Creating COM objects with nested Classes
class CMyComObject{
class CIMyComInterface : public IMyComInterface
{
provide implementations of all pure
virtual methods in IMyComInterface
}
CIMyComInterface m_im;
class CIYourComInterface : public IYourComInterface {
provide implementations of all pure
virtual methods in IYourComInterface
}
CIYourComInterface m_iy;
};
The advantage of this method is that the implementation of the COM class reflects the COM containment relationship,
for example the COM interfaces are contained in the COM object.
Our main interest is in using multiple inheritance because this is what ATL uses.
Using multiple inheritance
To use multiple inheritance, create a C++ implementation class for your COM object that inherits from the interface specifications in MyComInterface.h (the MIDL-generated include file from previous lessons):
class CMyComObject : public IMyComInterface,
public IYourComInterface
{
…
};
Class CMyComObject
must implement all methods from IMyComInterface
and IYourComInterface
.
Recall that each COM interface class is defined, either manually or via IDL, to inherit from (i.e. implement) IUnknown
- QueryInterface
, AddRef
, and Release
. At first glance it would seem that we need to implement the IUnknown
methods twice - once for IMyComInterface
and once for IYourComInterface
.
Doing so would cause a name conflict because we can not implement two identical methods with the same signature in a C++ class.
The following code fragment demonstrates how we handle this situation.
class CMyComObject : public IMyComInterface,
public IYourComInterface {
HRESULT __stdcall QueryInterface
(const IID& iid, void **ppv);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
//Methods for IMyComInterface
- excluding IUnknown
HRESULT __stdcall Fx1(CHAR *buf);
HRESULT __stdcall Fx2();
//Methods for IYourComInterface
- excluding IUnknown
HRESULT __stdcall Zx1(LONG ix);
};
When the Visual C++ compiler sees both base classes defining the methods with the same signature, it expects only one implementation of these methods in the derived class. The compiler actually generates two vtables
within the CMyComObject
class object, one for each interface.
The IUnknown
entries of each vtable
point to the shared methods. We do not need to specify each function as virtual because the base classes do this.
CLSID
Like COM interfaces, COM objects are identified by a 128-bit ID or UUID. When used to identify a COM object, the IDs are called CLSIDs.
The DEFINE_GUID macro can be used to define a variable representing a CLSID.
Clients and objects have different views of a COM object and its interfaces. The object sees the interface implementation via its internal C++ class. The client views the object through its interfaces, that is, its vtables.
Implement Com 0bject - Exercise
Click the Exercise link below to apply what you have learned about implementation of a COM object using multiple inheritance.
Implement Com 0bject - Exercise
.NET COM Complete Interoperability