Component object model basics pdf


















A COM object is an instance of a coclass in memory. Registration is the process of creating registry entries that tell Windows where a COM server is located.

Unregistration is the opposite - removing those registry entries. A GUID rhymes with "fluid", stands for g lobally u nique id entifier is a bit number. Each interface and coclass has a GUID. You will also see the term UUID which stands for u niversally u nique id entifier at times.

It is not a "handle" to anything, despite the H prefix. Every language has its own way of dealing with objects. Now, in between those two stages of creating and destroying the object, you actually have to use it.

If the object is created successfully, the COM library returns a pointer to the requested interface. The prototype for CoCreateInstance is:. When you call CoCreateInstance , it handles looking up the CLSID in the registry, reading the location of the server, loading the server into memory, and creating an instance of the coclass you requested. As stated before, you don't free COM objects, you just tell them that you're done using them. You call this method to tell the COM object that you no longer need it.

Once you call Release , you must not use the interface pointer any more, since the COM object may disappear from memory at any time. If your app uses a lot of different COM objects, it's vitally important to call Release whenever you're done using an interface. If you don't release interfaces, the COM objects and the DLLs that contain the code will remain in memory, and will needlessly add to your app's working set.

The name is a bit misleading, in that it's not an unknown interface. We've already seen Release in action, but what about QueryInterface? If the COM object implements more than one interface not counting IUnknown , you use QueryInterface to get any additional interface pointers that you need. The prototype of QueryInterface is:.

Let's continue our shell link example. If it succeeded, you can then use the new interface pointer, pIPF , just like any other interface. In real COM, clients would get a class object first and then ask the class object to manufacture the real object in much the same way MFC does dynamic creation.

GetClassObject has the following three parameters:. The second parameter, nIid , is the unique identifier of the interface that we want. The third parameter is a pointer to an interface to the object. Remember that we're going to be dealing with interfaces now, which are different from classes. As it turns out, a class can have several interfaces, so the last two parameters exist to manage interface selection.

The function returns TRUE if the call is successful. Now let's go back to the design of CSpaceship. We haven't really explained spaceship interfaces yet. These functions completely control some aspect of derived class behavior. For CSpaceship , let's write an interface named IMotion , which controls the spaceship object's position. For simplicity's sake, we'll declare just two functions, Fly and GetPosition , and we'll keep things uncomplicated by making the position value an integer.

The Fly function calculates the position of the spaceship, and the GetPosition function returns a reference to the current position. Here are the declarations:. The actual code for the spaceship-related functions, including GetClassObject - is located in the component part of the program. The client part calls the GetClassObject function to construct the spaceship and to obtain an IMotion pointer.

Both parts have access to the IMotion declaration at compile time. Here's how the client calls GetClassObject :. As you can see, the CSpaceship class implements the Fly and GetPosition functions and our main program can call them for the one particular spaceship object, as shown here:. Now the spaceship is off and flying. We're controlling it entirely through the pMot pointer. Notice that pMot is technically not a pointer to a CSpaceship object. Let's make things a little more complex by adding a second interface, IVisual , which handles the spaceship's visual representation.

One function is enough - Display. Here's the whole base class:. Are you getting the idea that COM wants you to associate functions in groups? You're not imagining it. But why? Well, in your space simulation, you probably want to include other kinds of objects in addition to spaceships. Imagine that the IMotion and IVisual interfaces are being used for other classes. If you "published" your IMotion and IVisual interfaces, perhaps other space simulation software companies would adopt them.

Think of an interface as a contract between two software modules. The idea is that interface declarations never change. If you want to upgrade your spaceship code, you don't change the IMotion or the IVisual interface; rather, you add a new interface, such as ICrew. The existing spaceship clients can continue to run with the old interfaces, and new client programs can use the new ICrew interface as well. These client programs can find out at runtime which interfaces a particular spaceship software version supports.

With the ordinary constructor, you obtain one object with one batch of member functions. With the GetClassObject function, you obtain the object plus your choice of interfaces. As you'll see later, you start with one interface and then use that interface to get other interfaces to the same object.

So how do you program two interfaces for CSpaceship? The MFC library uses nested classes instead , so that's what we'll use to illustrate multiple interfaces on the CSpaceship class. Here's a first cut at nesting interfaces within the CSpaceship class:. We'll make them data members of CSpaceship because that strategy is more compatible with the MFC macros, as you'll see later.

In COM, this parent class is known as the class with object identity. To understand COM and therefore all COM-based technologies , it is crucial to understand that it is not an object-oriented language but a standard.

Nor does COM specify how an application should be structured; language, structure, and implementation details are left to the application developer. Rather, COM specifies an object model and programming requirements that enable COM objects also called COM components, or sometimes simply objects to interact with other objects.

These objects can be within a single process, in other processes, and can even be on remote computers. They can be written in different languages, and they may be structurally quite dissimilar, which is why COM is referred to as a binary standard ; a standard that applies after a program has been translated to binary machine code.

Figure 2. Virtual function tables VTBL. 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. 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. 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. In COM, applications interact with each other and with the system through collections of functions called 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:. Given that an interface is a contractual way for a COM component to expose its services, there are several very important points to understand:.

It is convenient to adopt a standard pictorial representation for COM components and their interfaces. The current convention is to draw each interface on a COM component as a "plug-in jack. Figure 3. Figure 4. Interfaces extend towards the clients connected to them. Figure 5. Two applications may connect to each other's objects, in which case they extend their interfaces towards each other. The unique use of interfaces in COM provides five major benefits:. The ability for functionality in applications clients or servers of COM components to evolve over time.

QueryInterface allows a COM component to make more interfaces available to new clients that is, support new groups of functions while at the same time retaining complete binary compatibility with existing client code. In other words, revising a COM component by adding new functionality will not require any recompilation of any existing clients of that component. This is a key solution to the problem of versioning, and is a fundamental requirement for achieving a component software market.

COM additionally provides for robust versioning because COM interfaces are immutable, and COM components continue to support old interfaces even while adding new functionality through additional interfaces. This guarantees backwards compatibility as components are upgraded. Other proposed system object models generally allow developers to change existing interfaces, leading ultimately to versioning problems as components are upgraded. This freedom in other object models to change interfaces may appear on the surface to handle versioning, but in practice it does not work.

For example, if version-checking is done only at object creation time, subsequent users of an instantiated object can easily fail because the object is of the right type but the wrong version. Per-call version-checking is too expensive to even contemplate! Fast and simple object interaction. Once a client establishes a connection to a COM component, calls to that COM component's services interface functions are simply indirect functions calls through two memory pointers. As a result, the performance overhead of interacting with an in-process COM component an COM component that is in the same address space as the calling code is negligible.

In addition, using multiple interfaces per object is efficient because the cost of negotiating interfaces via QueryInterface is done in groups of functions instead of one function at a time.

Interface reuse. Design experience suggests that there are many sets of operations that are useful across a broad range of components. For example, it is commonly useful to provide or use a set of functions for reading or writing streams of bytes. This not only allows for code reuse, but by reusing interfaces, the programmer learns the interface once and can apply it throughout many different applications.

A key point is that the caller makes this call exactly as it would for an object in the same process. The binary standard enables COM to perform inter-process and cross-network function calls transparently. Although there is, of course, more overhead in making a remote procedure call, no special code is necessary in the client to differentiate an in-process object from an out-of-process object.

This means that as long as the client is written from the start to handle RPC exceptions, all objects in-process, cross-process, and remote are available to clients in a uniform, transparent fashion. Microsoft will be providing a distributed version of COM that will require no modification to existing components in order to gain distributed capabilities.

In other words, programmers are completely isolated from networking issues, and components shipped today will operate in a distributed fashion when this future version of COM is released. Programming language independence. Any programming language that can create structures of pointers and explicitly or implicitly call functions through pointers can create and use COM components.

COM components can be implemented in a number of different programming languages and used from clients that are written using completely different programming languages. Again, this is because COM, unlike an object-oriented programming language, represents a binary object standard, not a source code standard. COM uses globally unique identifiers GUIDs , which are bit integers that are guaranteed to be unique in the universe across space and time, to identify every interface and every COM component class.

Human-readable names are assigned only for convenience and are locally scoped. This helps ensure that COM components do not accidentally connect to the "wrong" component, interface, or method, even in networks with millions of COM components. Microsoft supplies a tool uuidgen that automatically generates GUIDs.

Through the use of defines, developers don't need to be exposed to the actual bit GUID. The GUIDs are embedded in the component binary itself and are used by the COM system dynamically at bind time to ensure that no false connections are made between components.

COM defines one special interface, IUnknown , to implement some essential functionality. Figure 6 is a graphical representation of IUnknown. Figure 6.



0コメント

  • 1000 / 1000