Tricks of the Windows Game Programming Gurus:DirectX Fundamentals and the Dreaded COM

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

`QueryInterface()` is the key to COM. It’s used to request a pointer to the interface functions that you desire. To make the request happen, you must have an interface ID. This is a unique number, 128 bits long, that you assign to your interface. There are 2128 different possible interface IDs, and I guarantee that we wouldn’t run out in a billion years even if everybody on this planet did nothing but make COM objects. More on the interface ID when we get to a real example a little later in the chapter.

Furthermore, one of the rules of COM is that if you have an interface, you can always request any other interface from it as long as it’s from the same COM object. Basically, this means that you can get anywhere from anywhere else. Take a look at Figure 5.5 to see this graphically.

Figure 5.5 Navigating the interfaces of a COM object.

`AddRef()` is a curious function. COM objects use a technique called reference counting to track their life. This is due to one of the specifications of COM: It’s not language-specific. Hence, `AddRef()` is called when a COM object is created and when interfaces are created to track how many references there are to the objects. If a COM object were to use `malloc()` or `new[]`, that would be C/C++-specific. When the reference count drops to 0, the objects are destroyed internally.

> Tip: Usually, you don’t have to call `AddRef()` yourself on interfaces or COM objects. It’s done internally by the `QueryInterface()` function. But sometimes you may have to, if you want to increase the reference count to trick the COM object into thinking that there are more reference to it than really are.

This brings us to a problem—if COM objects are C++ classes, how can they be created or used in Visual Basic, Java, ActiveX, and so on? It just so happens that the designers of COM used virtual C++ classes to implement COM, but you don’t need to use C++ to access them or even to create them. As long as you create the same binary image that a Microsoft C++ compiler would when creating a virtual C++ class, the COM object will be COM-compliant. Of course, most compiler products have extras or tools to help make COM objects, so that’s not too much of a problem. The cool thing about this is that you can write a COM object in C++, Visual Basic, or Delphi, and then that COM object can be used by any of those languages! A binary image in memory is a binary image in memory.

`Release()` is used to decrement the reference count of a COM object or interface. In most cases, you must call this function yourself when you’re done with an interface. However, sometimes if you create an object and then create another object from that object, calling `Release()` on the parent will trickle down and `Release()` the child or derived object. But either way, it’s a good idea to `Release()` in the opposite order that you queried.

#### More on Interface IDs and GUIDs

As I mentioned earlier, every COM object and interface thereof must have a unique 128-bit identifier that you use to request or access it. These numbers are called GUIDs (Globally Unique Identifiers) in general. More specifically, when defining COM interfaces they’re called Interface IDs or IIDs. To generate them, you must use a program called `GUIDGEN.EXE` created by Microsoft (or a similar program that uses the same algorithm). Figure 5.6 shows `GUIDGEN.EXE` in action.

Figure 5.6 The GUID generator `GUIDGEN.EXE` in action.

What you do is select what kind of ID you want (there are four different formats), and then the program generates a 128-bit vector that is guaranteed to never be generated again on any machine at any time. Seem impossible? It’s not. It’s just math and probability theory. The bottom line is that it works, so don’t get a headache asking why.

After you generate the GUID or IID, it’s placed on the Clipboard and you can paste it into your programs by pressing Ctrl+V. Here’s an example of an IID I just made while writing this paragraph:

    // {C1BCE961-3E98-11d2-A1C2-004095271606}

    static const <<name>> =

    { 0xc1bce961, 0x3e98, 0x11d2,

    { 0xa1, 0xc2, 0x0, 0x40, 0x95, 0x27, 0x16, 0x6 } };

Of course, you would replace `<<name>>` with the name you choose for the GUID in your program, but you get the idea.

GUIDs and IIDs (Interface IDs) are used to reference COM objects and their interfaces. So whenever you make a new COM object and a set of interfaces, these are the only numbers that you have to give to programmers to work with your COM objects. Once they have the IIDs, they can create COM objects and interfaces.

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.