Component Object Model (COM)

COM, or Component Object Model, is an object-based software architecture that allows applications to be built from binary software components.

What is Component Object Model (COM)?

As defined by Microsoft, the Component Object Model (COM) is an object-based software architecture that allows applications to be built from binary software components. COM is the foundation for various Microsoft technologies including OLE, ActiveX, Distributed COM (DCOM), COM+, and Microsoft Transaction Server (MTS).

Component Object Model (COM)
Component Object Model (COM)

COM is not a programming language, rather it is a specification. The goal of COM is to allow applications to be built using components. These COM components can be created by different vendors, at different times, and using different programming languages. Also, COM components can run on different machines and different operating systems.

The following concepts are fundamental to the way COM works:

  • COM Interfaces: A group of related functions implemented by the COM class. COM interfaces are the mechanisms by which COM objects expose their functionality to applications and other components. An interface is a table of pointers to functions that are implemented by the object. The table represents the interface and the functions to which the table points represent the methods of that interface. COM objects can expose multiple interfaces. Each interface has its own unique interface ID (IID). 
  • IUnknown: This is the basic COM interface on which all other interfaces are based; it provides reference counting and interface querying mechanisms. IUnknown allows navigation to all other interfaces exposed by the object. 
  • Reference counting: This is a mechanism by which an interface determines it is no longer being used and is, therefore, free to remove itself. IUnknown uses the methods AddRef and Release to implement reference counting. 
  • QueryInterface: This is the IUnknown method used to query an object for a given interface. 
  • Aggregation: This is a technique by which one object can make use of another. 
  • Marshaling: This mechanism lets objects be used across thread, process, and network boundaries, thus providing location independence. 

Component Object Model Fundamentals

The Component Object Model defines several fundamental concepts that provide the model’s structural underpinnings. These include:

  • A binary standard for function calling between components.
  • A provision for strongly-typed groupings of functions into interfaces.
  • A base interface providing:
    • A way for components to dynamically discover the interfaces implemented by other components.
    • Reference counting to allow components to track their own lifetime and delete themselves when appropriate.
  • A mechanism to identify components and their interfaces uniquely, worldwide.
  • A “component loader” to set up component interactions and, additionally (in the cross-process and cross-network cases), to help manage component interactions.

Binary Standard

For any given platform (hardware and operating system combination), COM defines a standard way to lay out virtual function tables (vtables) in memory, and a standard way to call functions through the vtables. Thus, any language that can call functions via pointers (C, C++, Smalltalk, Ada, and even BASIC) all can be used to write components that can interoperate with other components written to the same binary standard. Indirection (the client holds a pointer to a vtable) allows for vtable sharing among multiple instances of the same object class. On a system with hundreds of object instances, vtable sharing can reduce memory requirements considerably, because additional vtables pointing to the same component instance consume much less memory than multiple instances of the same component.

Virtual function tables (VTBL)
Virtual function tables (VTBL)

Objects and Components

The word object tends to mean something different to everyone. To clarify: In COM, an object is a piece of compiled code that provides some service to the rest of the system. To avoid confusion, it is probably best to refer to an object used in COM as a COM component or simply as a component. This avoids confusing COM components with source-code OOP objects such as those defined in C++. COM components support a base interface called IUnknown (described later), along with a combination of other interfaces, depending on what functionality the COM component chooses to expose.

COM components usually have some associated data, but unlike C++ objects, a given COM component will never have direct access to another COM component in its entirety. Instead, COM components always access other COM components through interface pointers. This is a primary architectural feature of the Component Object Model, because it allows COM to completely preserve encapsulation of data and processing, a fundamental requirement of a true component software standard. It also allows for transparent remoting (cross-process or cross-network calling) because all data access is through methods that can be accessed through a proxy-stub pair that forward the request from the client component to the server component and also send back the response.

COM Interfaces

In COM, applications interact with each other and with the system through collections of functions called interfaces. Note that all OLE services are simply COM interfaces. A COM “interface” is a strongly-typed contract between software components to provide a small but useful set of semantically related operations (methods). An interface is the definition of an expected behavior and expected responsibilities. OLE’s drag-and-drop support is a good example. All of the functionality that a component must implement to be a drop target is collected into the IDropTarget interface; all the drag source functionality is in the IDragSource interface.

Interface names begin with “I” by convention. OLE provides a number of useful general-purpose interfaces (which generally begin with “IOle“), but because anyone can define custom interfaces as well, developers can develop their own interfaces as they deploy component-based applications. Incidentally, a pointer to a COM component is really a pointer to one of the interfaces that the COM component implements; this means that you can only use a COM component pointer to call a method, and not to modify data, as described above. Here is an example of an interface, ILookup, with two member methods:

interface ILookup : public IUnknown
virtual HRESULT __stdcall LookupByName
( LPTSTR lpName, TCHAR **lplpNumber) = 0;
virtual HRESULT __stdcall LookupByNumber
( LPTSTR lpNumber, TCHAR **lplpName) = 0;

See also:

External References: