Intro

To start with something practical and maybe useful I thought that I’d write a little guide about how to COM properly in c++ under Win.

Now don’t get me wrong, I’m not pretending to be an expert in the field. It’s just that the world is full of misleading crap about COM all of which is a big unproductive time-waster.

If you are looking for information on why COM was devised or for documentation on it please look elsewhere.

There’s actually a nice description on Wikipedia that can start you off: http://en.wikipedia.org/wiki/Component_Object_Model or if you’re suicidal you can start with MSDN but don’t expect a lot of help from that place.

Otherwise, if you’re interested in seeing how to code a COM interface, implementation and its usage in c++ under Windows, do read on…

How does COM affect me as a programmer?

First of all many COM implementations in c++ assume you’re going to use classes and that polymorphism is your friend.

There’s nothing stopping you from doing COM in vanilla c using struct’s and whatnot – the Win SDK is nicely decorated for both a c++ and a c version of COM but I’ll stick to OOP today.

The main idea behind COM is to have so-called components (which are simply functionalities bundled up together due to their logical similarities) each one of which coming with one or more interfaces.

This lets you separate the code you write into 2 parts:

the interfaces

the implementations (or co-classes)

The interfaces are basically just classes with no members and with all their methods public and pure virtual. Furthermore, each COM-enabled interface class should inherit publicly from the IUnknown struct (yes! it’s a c STRUCT! but then in c++ a struct and a class are really the same thing). You don’t want any members in your interface classes because interfaces are by definition stateless and should store no information. Their only purpose is to expose a bunch of public methods to the outside world.

Why do the methods need to be pure virtual? Well, they don’t ALL need to be but the idea is that an interface class can’t be instantiated so you can either declare it as abstract, make its methods pure virtual or use __declspec(novtable) on it – actually the SDK’s do both of the last two things at the same time.

The implementations are also classes. They in turn inherit the interface’s methods and add their own state information. The interface methods become non-pure and may be non-virtual but they must be defined. It is possible to define a 1 to 1 relationship between an interface and an implementation or to implement several interfaces in one co-class or to have several co-class implementations for one interface. However you must know exactly what you’re doing if you intend to let this sort of mixing happen as COM asks that interfaces be retrievable symmetrically, reflexively and transitively (yes this is a shameless rip-off off Wikipedia).

COM Interfaces

So what happens when you inherit from IUnknown? Well, you get 3 pure virtual methods which is the barebones minimum for a COM interface:

public: /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE;

These scary definitions really boil down to this (look in Unknwn.h for a peek into IUnknown and into ObjBase.h for all these nifty macros):

public: virtual HRESULT __stdcall QueryInterface( const IID& riid, void** ppvObj) = 0; virtual unsigned long __stdcall AddRef() = 0; virtual unsigned long __stdcall Release() = 0;

AddRef and Release are book-keeping methods used to store reference counts to the interface. Since the interface itself has no members these methods and the reference count need to be implemented somewhere else (more about that later).

QueryInterface is the single point where all code will go through to retrieve an interface pointer in order to access its public methods. Or more precisely: their implementations but more about that later.

So essentially when you declare a COM interface you will want to do something like this and end up with the 3 methods shown above plus any specific methods you need in your interface:

class IMyInterface : public IUnknown { public: /*** IMyInterface methods ***/ virtual whatevertype MyMethod1(whatevertype2) = 0; };

This code will work – although it’s not really COM just yet. Let’s add two things to it: a GUID and some nifty macros from ObjBase.h.

A GUID or otherwise CLSID, IID, UIID (or whatever other name) is essentially a Global Unique Identifier – it is supposed to be global on a universal scale so that each and every single COM object can have its own unique GUID.

A GUID is basically a very long number stored in a struct in guiddef.h as

typedef struct _GUID { unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[ 8 ]; } GUID;

Usually you will get a unique GUID from a generator such as GUIDGEN.EXE or any other standard-compliant generator. There are some generators on the web too but frankly I’ve never used them so I can’t say if they’re any good.

If you’re using MS Visual Studio GUIDGEN.EXE is installed in there, just go to the Tools menu or use Visual’s COM wizard to build a bare component automatically.

If you’ve got Visual Express or another compiler that doesn’t come with such a tool then you can download it from http://www.microsoft.downloads.com – search for guidgen.exe.

Once you run the tool it pops up with a fresh GUID. Just select the format you want and click copy to grab it into the clipboard.

You will most often need the Registry format “00000000-0000-0000-0000-000000000000” or the DEFINE_GUID one (we’ll use both here).

As for the nifty macros we will use here’s a brief description of what they do:

DEFINE_GUID(name, …)

This comes from ObjBase.h and declares a GUID struct variable with the “name” symbol. Also if INITGUID is #define-d this struct will be initialized using the rest of the macro parameters.

You’ll probably want to pass something like IID_IMyInterface as the name followed by the DEFINE_GUID form of your generated GUID.

This comes from ObjBase.h and declares a GUID struct variable with the “name” symbol. Also if INITGUID is #define-d this struct will be initialized using the rest of the macro parameters. You’ll probably want to pass something like IID_IMyInterface as the name followed by the DEFINE_GUID form of your generated GUID. DECLSPEC_UUID(x)

This comes from WinNT.h and aliases the __declspec(uuid(x)) declaration modifier. This modifier basically links a struct or class with which it is used with the given GUID – you will use the Registry format of your GUID here.

More info on __declspec(uuid(…)) can be found here http://msdn.microsoft.com/en-us/library/3b6wkewa%28VS.80%29.aspx

This comes from WinNT.h and aliases the __declspec(uuid(x)) declaration modifier. This modifier basically links a struct or class with which it is used with the given GUID – you will use the Registry format of your GUID here. More info on __declspec(uuid(…)) can be found here http://msdn.microsoft.com/en-us/library/3b6wkewa%28VS.80%29.aspx DECLARE_INTERFACE_(iface, baseiface)

This one comes from ObjBase.h. It is one of the 4 variants of DECLARE_INTERFACE. This particular macro aliases things like “interface” and __declspec(novtable) and also public inheritance from a base interface.

There are also 2 variants which add __declspec(uuid()) but we can do that using the DECLSPEC_UUID(x) macro with a forward declaration – see sample code below.

Typically you’ll want to use your interface name (e.g. IMyInterface) for iface and IUnknown for baseiface.

This one comes from ObjBase.h. It is one of the 4 variants of DECLARE_INTERFACE. This particular macro aliases things like “interface” and __declspec(novtable) and also public inheritance from a base interface. There are also 2 variants which add __declspec(uuid()) but we can do that using the DECLSPEC_UUID(x) macro with a forward declaration – see sample code below. Typically you’ll want to use your interface name (e.g. IMyInterface) for iface and IUnknown for baseiface. STDMETHOD(method) and STDMETHOD_(type,method)

This pair is defined in ObjBase.h. They are used to declare interface methods but work equally well in co-classes. Both declare a method as virtual using __declspec(nothrow) and in __stdcall.

Where they differ is the return type – STDMETHOD declare the method to return a HRESULT whereas STDMETHOD_ asks for a return type in its first parameter.

Unless you are meek and compliant as I am, you can use either of the V-terminated macros (STDMETHODV and STDMETHODV_) which declare the methods in __cdecl instead.

Also note that in C these macros expand to function pointers.

This pair is defined in ObjBase.h. They are used to declare interface methods but work equally well in co-classes. Both declare a method as virtual using __declspec(nothrow) and in __stdcall. Where they differ is the return type – STDMETHOD declare the method to return a HRESULT whereas STDMETHOD_ asks for a return type in its first parameter. Unless you are meek and compliant as I am, you can use either of the V-terminated macros (STDMETHODV and STDMETHODV_) which declare the methods in __cdecl instead. Also note that in C these macros expand to function pointers. THIS_, THIS and PURE

All three of them are in ObjBase.h.

PURE expands to =0 to make methods pure virtual.

THIS expands to void. THIS_ expands to nothing. Use THIS when the method accepts no arguments and THIS_ when it accepts at least one.

However in C we cannot declare classes and there is no “this” pointer in function calls. However the interface functions need the “this” pointer and so these macros get uglier when __cplusplus is not defined or when CINTERFACE is.

In that case the macros expand to nothing, “INTERFACE FAR * This” and again “INTERFACE FAR* This,” respectively and things look less pretty;

here INTERFACE is something you must #undef and then #define to your interface name before you start each interface declaration (you’ll see this in the sample code below), FAR is just far (whatever the hell it does these days) and This is the name of the makeshift this* that this code tries to pass off into the interface calls.

Ok whew, now that we have this reference let’s write an interface declaration. Let’s say our GUID is just a bunch of zeroes (which by the way is a NULL GUID and is not valid) and let’s stick to our IMyInterface name. The sample interface declaration actually follows the DirectX scheme so if you do any DX programming you might be familiar with the way it’s done here.

/*****************/ /* IMyInterface.h */ /*****************/ #pragma once #ifndef IMYINTERFACE_H #define IMYINTERFACE_H namespace mynamespace { // Interface IID's #if defined( _WIN32 ) && !defined( _NO_COM) // IID_IMyInterface // {00000000-0000-0000-0000-000000000000} DEFINE_GUID(IID_IMyInterface, 0x00000000, 0x000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); #endif #ifdef __cplusplus #ifndef DECLSPEC_UUID #if _MSC_VER >= 1100 #define DECLSPEC_UUID(x) __declspec(uuid(x)) #else #define DECLSPEC_UUID(x) #endif #endif // Forward declaration of IMyInterface with GUID "00000000-0000-0000-0000-000000000000" interface DECLSPEC_UUID("00000000-0000-0000-0000-000000000000") IMyInterface; #if defined(_COM_SMARTPTR_TYPEDEF) _COM_SMARTPTR_TYPEDEF(IMyInterface, __uuidof(IMyInterface)); #endif #endif typedef interface IMyInterface IMyInterface; #ifdef __cplusplus extern "C" { #endif // this is for the benefit of C mangling the declaration #undef INTERFACE #define INTERFACE IMyInterface // My Interface DECLARE_INTERFACE_(IMyInterface,IUnknown) // This re-declaration is same as: interface __declspec(novtable) IMyInterface : public IUnknown { public: // same as: virtual __declspec(nothrow) HRESULT __stdcall MyMethod1(char* ptr,const int i=1) = 0; // in C it expands to HRESULT (__stdcall * MyMethod1)(IMyInterface far * This, char* ptr, const int i=1); STDMETHOD (MyMethod1)(THIS_ char* ptr, const int i=1) PURE; // same as: virtual __declspec(nothrow) long __stdcall MyMethod2(void) = 0; // in C it expands to long(__stdcall * MyMethod1)(IMyInterface far * This) STDMETHOD_(long,MyMethod2)(THIS) PURE; }; #ifdef __cplusplus }; #endif }; // mynamespace #endif //IMYINTERFACE_H

So what did we do there? Well, basically we declared a GUID struct which we named IID_IMyInterface with the GUID number – this is what we did with DEFINE_GUID. We’re going to be using this name IID_IMyInterface later as the identifier of our interface.

Then we made a forward declaration on IMyInterface and assigned the GUID to it. By the way you might notice that IMyInterface is defined as a struct not a class or “interface” – do not confuse the keyword “interface” in managed C++ with what really goes on here; if you look at the beginning of ObjBase.h you’ll see that there are a couple of lines which go:

#define __STRUCT__ struct

#define interface __STRUCT__

This isn’t anything fancy but it’s enough to make my IDE totally clueless as to what “interface” really is.

Finally we re-declared IMyInterface as a struct and added a novtable modifier and an IUnknown public inheritance, plus two additional pure virtual methods.



In any case IMyInterface is abstract cannot be initialized.

Next, we will see how this interface can be implemented.