Simplifying the Concept of COM

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Environment: C/C++

The odd thing about COM, C++, and C…

Like most average people, I talk about COM, use COM, and program COM without knowing what it is—until I decided to go back and see what it is. If you have the same curiosity, join me for some fun.

For years, I’ve known that if I have a pointer to an IUnknown, I can do a lot of things. So, let’s look at the mysterious IUnknown. We can find it in the header file “unknwn.h,” supplied by Microsoft. Don’t try to understand everything in there. In fact, let’s go the reverse way: Ignore everything except the things that we are interested in. And what follows is what we want: {skip it if you don’t like it}.


#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE(“00000000-0000-0000-C000-000000000046”)
IUnknown
{
public:
BEGIN_INTERFACE
virtual HRESULT STDMETHODCALLTYPE QueryInterface
(REFIID riid, void **ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
END_INTERFACE
};
#else /* C style interface */
typedef struct IUnknownVtbl
{
BEGIN_INTERFACE
HRESULT (STDMETHODCALLTYPE *QueryInterface)(IUnknown *This,
REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef)(IUnknown *This);
ULONG (STDMETHODCALLTYPE *Release)(IUnknown *This);
END_INTERFACE
} IUnknownVtbl;

interface IUnknown
{
CONST_VTBL struct IUnknownVtbl *lpVtbl;
};
#endif

We further ignore !defined(CINTERFACE), MIDL_INTERFACE("00000000-0000-0000-C000-000000000046"), BEGIN_INTERFACE, and END_INTERFACE. The HRESULT and ULONG are equivalent to a 32-bit integer, so we treat them as unsigned. The STDMETHODCALLTYPE is finally resoved to __stdcall. The REFIID is resolved to a reference (or a pointer if the code is writing in C) to a structure that identifies the interface ID, so we leave it unchanged. The CONST_VTBL will resolve to const. Now what we have is:


#if defined(__cplusplus)
IUnknown
{
public:
virtual unsigned __stdcall QueryInterface(REFIID riid,
void **ppvObject) = 0;
virtual unsigned __stdcall AddRef( void) = 0;
virtual unsigned __stdcall Release( void) = 0;
};
#else
typedef struct IUnknownVtbl
{
unsigned (__stdcall *QueryInterface)(IUnknown *This, REFIID
riid, void **ppvObject);
unsigned (__stdcall *AddRef)(IUnknown *This);
unsigned (__stdcall *Release)(IUnknown *This);
} IUnknownVtbl;

interface IUnknown
{
const struct IUnknownVtbl *lpVtbl;
};
#endif

Try to understand the preceding code; simplifying it further, we have:


#if defined(C++)
ISomeInterface
{
public:
some pure function(s)…
};
#else
typedef struct ISomeInterface_Vtbl
{
some function pointer(s)…
} ISomeInterface_Vtbl;

interface ISomeInterface
{
const struct ISomeInterface_Vtbl *lpVtbl;
};
#endif

Now our conclusion is: In C++, ISomeInterface is just an abstract class with some pure functions and in C, ISomeInterface is simply a pointer to a struct that contains some function pointers. Drawing the equivalence between them, we have the following core knowledge about COM, C++, and C:

A C++ class/struct (or a COM interface) is simply a pointer to a table of pointers to something. Ah, ha!—How simple it is!

From now on, don’t think COM, don’t think C++, but C pointers. We are already familiar with C pointers. They are small, fast, and can do a lot of things. That’s what I want to say. We’ll then try to find some ways to play with them.

Note: The words table, array, and struct can be used interchangably with each other as long as we agree on their meaning. Also, we don’t care about a class’s data member yet. We’ll deal with that sometime later.

A little bit about the __stdcall: It is just an agreement between the caller and what is being called, so that the item being called knows how to accept the call, and the caller knows how to make a call. The This pointer needs a little bit more description, we’ll talk about it next time.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read