COM: The Component Object Model

By Adrian Perez


If you want to link/mirror/reprint this document, please tell me beforehand.  Not that I won't let you, I just want to know what's happening with stuff I write.

If you've used DirectX, you've probably heard of COM.  You've probably used QueryInterface and scratched your head, wondering why such seemingly unneeded complexity was added to the API.  This doc is a stab at explaining what COM is, why it's useful, and how to use it.

1.) COM: What it is

COM, (Component Object Model) isn't a language, it isn't a protocol... all it is, is a way to write programs.  It's language independent, you can write COM objects in the programming language of your choice from C to Visual Basic, but it's design is directed towards C++'s Object Oriented Programming (OOP) model.  

A COM object, like the idealistic C++ OOP'ized class, is a piece of code that accomplishes a certain task.   For the sake of example, I'll use DirectDraw. COM objects have no public member variables, only functions (they're typically called 'methods', though).  The functions are grouped together into 'interfaces'.  Other code can only access the functionality of the object through the object's interfaces.  Interfaces are kind of a contract between the object developer and the object user.  When you, for example, use DirectDrawCreate(), you get in return a LPDIRECTDRAW pointer.  This is a pointer to an interface.  You can't see any of the internals of the DirectDraw object, you just have the interface.  You can use any function in the interface, and you know that once you compile your program with the description of the LPDIRECTDRAW interface, YOUR CODE WILL ALWAYS WORK whenever the DirectDraw object is installed on someone's machine.  The number of functions, nor their name, will NEVER change.  that is a key point of COM.

However, what if Microsoft wants to add functionality to DirectDraw?  It's no problem, as long as they don't change the original interface.  To add functionality to a COM object, you make a new interface with new functions that use the new functionality, which would be called, say, LPDIRECTDRAW2.  COM requires a lot  more planning ahead, you have to be very careful when you design your interfaces, or else you'll keep on adding features you forgot and get up to LPDIRECTDRAW50.... which is counter-productive.  COM requires a bit more design to be in place before code is written.

There's one big piece missing: if DirectDrawCreate() gives us a LPDIRECTDRAW pointer, how on earth do I get a LPDIRECTDRAW2 pointer (or in the example of DX6, LPDIRECTDRAW4).  Once you have an interface to an object, you can get ANY other interface that object supports by using Query Interface.  This way, old code can continue using the LPDIRECTDRAW interface, and newer code can support newer features by querying for LPDIRECTDRAW2, 3, 4, whatever.  Old code never breaks, new code can use new features.   Neat, huh?  With automation, your object can even describe it's interfaces and functions to other code, but that's a wee bit beyond the scope of this document.

2.) COM: Why it's there

COM is there for the very reasons I outlined above.  The objective is to create an object system such that old code that wants to use an object will never break because of versioning.  However, this doesn't hold back newer code from using new features, outside of a few QueryInterfaces here and there.  Turning code into a set of objects has a lot of advantages.  For example, let's say someone kindly made and registered a 'SpellChecker' object.  with this object, you could use it's ISpellCheck interface to spell check a block of text.  Ta-da, now your code has spell checking.   lets say that this same 'SpellChecker' eventually adds grammar correction to a new interface, then other people could use the old interface to do spell checking, or query for the new one to do grammar checking.  It's a very cool concept.

That of course begs the question how you get these interfaces. Ever wonder what the hell goes into the registry?  well, a lot of it is filled with registered COM objects.  Each interface and each object is stored with a Globally Unique IDentifier (GUID).  if you look up the definition of IID_DirectDraw4 in your headers, you'll see a long string of hex numbers, representing a GUID.  GUID's are huge.  They're more unique than anything you could possibly want, guaranteed unique both over time and space (the GUID uses a timestamp that won't turn over till the year 3000, and your unique network adapter ID.  If no network card is in your box, another unique number is used in it's place).  There is code inside DirectDrawCreate that goes to the registry, looks up the object's GUID, pulls the DLL name out of the registry, loads it, and initializes it, returning the pointer to the DirectDraw interface.  There's a lot of stuff that happens between getting the DLL and getting the interface, but we don't need to worry about that really.

3.) COM: How to use it

COM is far to big to try to explain in a simple document.  I can only touch upon the very basics.  If you're interested in writing your own COM objects, you'll need to know a lot more.  I recommend the book "Inside COM" (Microsoft Press).  

All COM interfaces are inherited from an interface called IUnknown.  it has the 3 following pure virtual functions:

Essentially, what this means for the byte-jockey is the first 3 entries in every v-table for every interface and object are those 3 functions.  AddRef and Release allows an object to be persistent.  the OS can stick the object code in a different process, and it will stay there.  Other processes can AddRef to use it, Release when they're done.  as soon as nobody is using it (when refcount is zero) the object will de-initialize itself and call delete this; (don't try this at home, kids).  

There is a lot more to COM, including DCom, which is the same idea, but instead of the same process, the other object can reside on a different machine running a different operating system on a different processor architecture.  However, for using most simple COM objects, this should get you on your feet.


Well, that's all.  Hope you liked it.  If you did, may I shamelessly plug my book that's coming out in Spring 2000? :)  While you're looking for places to go, you can see my website.

Rock on,

-Cuban