Component Object Model (COM)

The demand for businesses to deploy solutions across multiple servers is bound to increase. With the growth and acceptance of the Internet, businesses have come to think of their applications and information be connected and distributed across multiple servers from remote locations. Also data can be processed and accessed through the use of Web browsers and by user interfaces. But a number of problems stands on the way towards developing and deploying mission-critical business applications on several server systems. These applications are named as distributed software applications. They are communication issues among different programming languages and platforms and security. There are a few promising technologies for promoting these critical applications.. Microsoft has come out with a new technology called as Component Object Model (COM) that addresses these problems towards the goal of design of distributed software components.

What is COM

COM is an outgrowth of the OO technology. It is a specification that is based on a binary standard for reuse through interfaces. That is, components, which are pre-compiled blocks of code, written for COM can be reused without any dependencies on the language in which they are coded. The programming language may be Visual Basic, C++ etc.

COM uses system-level code that is implemented in the form of dynamic link libraries, which are collectively called COM library. The COM library consists of several application programming interface (API) functions that are necessary for COM components to do various tasks. COM library is responsible for locating and activating server applications. With client applications, COM APIs contains the necessary functions for instantiating objects that the client want to use. Also the COM library provides locator services using the System Control Manager (SCM), which also provides transparent remote procedure calls when an object is executing out-of-process in a local or remote server.

Component-based Development (CBD)

CBD came from OO software development methodology towards facilitating software reusability in larger scale. Suppose there is an object and we want to use that in an application. For that, we have to cut and paste the code in the application. If there is any changes made in the object, we have to search for all the object copies in the application to insert the relevant changes. This becomes cumbersome when there are more applications with more copies of the same object. Here comes the idea of designing components as a robust solution. A component can be technically defined as a coarse-grained object. It is also defined as a reusable software module, which displays its services through interfaces for use by client software. On using a component, which is stored in a single place, applications can use the object directly from the component and get the same functionality. Thus both classes, where objects get derived from and components provide same type of services. Classes pro! vide services to single applications because they can not communicate with other applications due to the differences in language and platform, while components provide services to numerous applications irrespective of the languages used. There came a number of architecture for developing both client-side and server-side components. They are OMG's CORBA, Sun's JaveBeans and Enterprise JavaBeans and Microsoft's COM. Thus the world is full of software components, which in turn can be of greater use for hundreds of different applications. As both CORBA and COM supports language independence, a different software vendor can create components using different programming languages without any integration problems. Click for an overview of components.

Advantages of COM

1. COM promotes component-based software development - before component-based development came, software programs have been coded using procedural programming paradigm, which supports linear form of program execution. But component-based program development comes with a number of advantages, such as the ability to use pre-packaged components and tools from third party vendors into an application and support for code reusability in other parts of the same application.

2. COM promotes code reusability - standard classes are normally reused in the same application but not to be used easily in other applications. But COM components are designed to separate themselves from single applications and hence can be accessed and used by several different applications without any hassle.

3. COM promotes Object-oriented programming (OOP) - The primary characteristics of OOP are encapsulation, which allows the implementation details of an object to be hidden, polymorphism, which is the ability to exhibit multiple behaviors, and inheritance, which allows for the reuse of existing classes in order to design new and more specialized classes. Among these, encapsulation is one of COM's most important characteristics. Encapsulation helps to hide how an object has implemented a method internally. This ultimately helps to incorporate more vigorously implemented or advanced implementation into an object at later time without affecting the client which uses it.

4. COM comprises the necessary mechanisms for COM components to communicate with each other - In the normal case, two components coded using two different programming languages can not communicate with each other. But COM can make it possible for different language components, which adhere to the COM specification, to interact with each other and hence COM is language-independent.

5. COM helps to access components loaded in different machines on the network - COM component can reside anywhere on our computer or even on another computer connected to a network. That is, applications using COM can access and share COM components regardless of their locations. Thus COM abstracts away the nitty-gritty of clients to locate COM components anywhere in the network. Thus COM provides location transparency and COM components are location independent.

COM Interfaces

Components, especially server-side ones, are bound to have their own interfaces. An interface is simply a list of methods a COM component implements and makes them available to consumers. COM interface are immutable. That is, once a COM component has been released with an interface, this interface must never be manipulated. COM interfaces are the mechanisms by which a client contacts, connects and use components. If the client component is using a different language from the one a server component is coded, there will be language problem for interactions. In order to remove this barrier, COM interfaces provide an universal way so that components coded in different languages can communicate with each other. Thus every interface constitutes a binding contract between a COM object (no interface is attached with this) and a COM component with an interface. COM specification makes life easier by allowing a component to publish more than one interface at a time. New interfaces can! be incorporated to support new features of the components while keeping the original interface intact. We have to increment a version number for the new interface. A class module then would need to be implemented for both old and new interfaces in order to support both old clients that rely on the old interface and new clients that can take advantage of the new interface. Thus the immutability factor of COM interfaces can be overcome.

Interface Definition Language (IDL)

To successfully make COM language-independent, the COM interfaces have to coded using IDL. IDL is just a declaration language, not a programming language. The syntax for IDL is almost similar to C++ language. But IDL goes beyond what C++ can offer by being able to define functions that extend process boundaries. IDL provides many vital extensions that allow attributes such as type libraries, co-classes, interfaces, and method parameters to be specified quite elegantly. But if there is no language problem, it is not mandatory to use IDL for defining COM interfaces.

Here comes an model interface definition for a COM component coded using Microsoft IDL.

[ object,
uuid (122323FAGAd098776)
]
interface IFindSum : IUnknown
{
import "unknown.idl"
HRESULT SumOfNumbers ( [in] long lnum1, [in] long lnum2, [out, retval] long* sum);
}

The interface definition begins with an object attribute. The object attribute is used to identify a COM interface. Then a UUID (universally unique identifier), which provides an unique identifying number ( a string of hexadecimal digits ) for each interface and this number is being generated by an algorithm, which takes into account the unique value from the network card on the programmer's PC and the current system date and time, follows that. The interface keyword is followed by the name of the interface (IFindSum).

The letter I in the interface name helps to identify that this is an interface. Following IFindSum is a colon and then the interface name IUnknown, the base interface and every COM object has to have this interface. IUnknown has three methods that a client can invoke: QueryInterface, AddRef, and Release.

The QueryInterface method is the mechanism that a client uses to discover and navigate the interfaces of a component dynamically. It is the most significant method of all COM interfaces available for a component since this method allows run-time checking of all of these interfaces. When the QueryInterface method provides an interface pointer to a client, the QueryInterface calls the method AddRef. The only way to access a COM object is through a pointer to an interface.

An interface pointer is actually a pointer to a pointer in a virtual table that is implemented in memory. That is, for every class that contains public methods, a virtual table will be created and placed in memory at run time. Virtual tables are generated for each class and not for objects of that class. Each virtual table contains an array of function pointers whose elements contain the address of each specific function that an object can implement. At the top of every virtual table array will be three fundamental methods that make up this IUnknown interface.

The methods AddRef and Release manage reference counting. This reference count is an internal count of the number of clients using a particular COM object . It is possible for several clients to invoke the services available with a COM object at the same time. When a client begins a session with an object, it calls the AddRef method, which increments one to the existing count. Once the session is over, the corresponding Release method gets invoked to decrement one from the existing count.

The next line down is used to locate the definition for the base interface IUnknown The next line identifies the interface method "SumofNumbers". This interface method is designed to return an HRESULT value.

An HRESULT is used with COM to indicate whether a method call is successfully accomplished or not. Almost all COM interfaces return a special 32-bit code, called as HRESULT, from their methods to return status information. It is actually the method COM utilizes to return errors to the caller of the method. The reason for this mechanism is due to the inability of COM to transmit error messages back to the client if there is anything wrong on the server side or on the way to the server. As components are being written using different programming languages and each language follows its own exception mechanisms, COM can not correctly pass on the error messages and hence HRESULT.

Following the HRESULT are three parameters for the interface method SumOfNumbers. The [in] in the first two parameters specifies that these parameters are input values to be passed to the interface method and the [out, retval] in the last parameter indicates that this parameter returns a value that will be ultimately passed to back to the client.

Windows Registry and Components Environment

COM components may be loaded in different address spaces in the same machine or machine connected with the network. Before an object can be created, the COM runtime must first locate the COM components. The COM runtime is able to locate COM components through the use of Windows registry.

COM components may be out-of-process or in-process. An out-of-process component can effectively be a separate program containing objects. This type runs in its own process space and will thus be largely independent from any client programs. These components are often large applications themselves, and provide access to their objects to make it easy for other programs to create macros or otherwise make use of existing functionality. This can be very beneficial, because the component developer can choose his own threading models. The drawback here is that the developer has to write the code for threading. This work can be handled by automatically COM+ , the latest one from the COM family.

There is also a performance issue. Because the client application is communicating with objects which are in an entirely different process there is quite a bit of overhead. COM steps in between the client and the server and handles all the communication between them. Mainly out-of-process components are useful if we are trying to make use of the objects in a pre-existing application.

An in-process component is one where the objects run inside the client's process. Each client gets its own private copy of the component and hence a copy of all the objects in that component. An in-process component is often called COM DLLs or ActiveX DLLs. In-process component does not have a process of its own and it always runs within the context of another process. Often this other process is the client application itself but may be run within the context of a different process entirely. In this case, we can get performance boost as the component is loaded in the client application itself. There is almost no overhead when client interacts with an object that is running in the same process. The major advantages of having in-process components are stability and increased manageability

Creating a COM object

There is a lot of communication that must occur behind the scenes in order for a COM object to be created. First of all, a client looking for an object has to make a call to an API function called CoCreateInstance with the CLSID for the class, which comprises the particular object. The prefix Co in this function is a typical naming convention for COM runtime API functions. CoCreateInstance in turn as a second step calls another API function called CoGetClassObject. Basically the function CoCreateInstance asks the SCM to search the Windows registry location, which is HKEY_CLASSES_ROOT\CLSID. The function of SCM is to locate the requested class object by using the specified CLSID. The first place the SCM looks to locate the class object is within its own internal database. If the class is not located inside its database, the SCM turns to the system registry as a third step. As soon as the class object is found, the SCM immediately returns to COM an interface pointer referred to as IClassFactory.

Every COM class must have a factory object associated with it. The main purpose of these class objects is to implement the IClassFactory interface. Once the client gets the IClassFactory pointer, two things happen. One, by obtaining a pointer to the IClassFactory, CoCreateInstance can call IClassFactory::CreateInstance in order to create the requested COM object. Once the object is created, a second step occurs: the interface pointer to the IClassFactory gets released.

The interface called IClassFactory's job is to talk to other class objects. Further, CoGetClassObject is a COM class object whose sole purpose is to create a new instance of a different class. Because this COM class creates class objects by implementing the IClassFactory interface, CoGetClassObject is referred to as a class factory.

LockServer

When an object is created it resides in memory. It is the client's job to notify the object when it is no longer needed. The Release method told above can decrement the reference count for the interface. If there are several interfaces for an object, it is possible that the object is still being accessed somewhere else. The idea is that the reference count has to reach zero before the object is to be released from the memory. Releasing objects from memory usually improves performance. Some special clients constantly create and destroy objects, which normally affects the application's performance. The LockServer method allows components to remain in memory by incrementing the reference count by one. Because LockServer keeps a count of one in the reference counter, the object will stay in memory even if it is not being accessed currently. Having the component reside in memory has the advantage of allowing the object to be called without having to go through the process of recre! ating it. But on the other hand, if objects are not destroyed when they are not in use, there will be reduction of system memory resources.

Click for Web resources COM Web resources

Back to my Home Page