0% found this document useful (0 votes)
34 views

COM: A Brief Introduction: Dan Berger

COM provides a binary standard for building reusable software components. It defines interfaces using UUIDs and allows querying objects to determine if they support a given interface. Objects support the IUnknown interface for reference counting. COM allows activating and obtaining objects from the SCM by CLSID, ProgID, or interface. While efficient for in-process use, COM also specifies marshaling for inter-process communication using remote procedure calls. The definitive references are the COM specification and Essential COM book.

Uploaded by

Anil Dogra
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views

COM: A Brief Introduction: Dan Berger

COM provides a binary standard for building reusable software components. It defines interfaces using UUIDs and allows querying objects to determine if they support a given interface. Objects support the IUnknown interface for reference counting. COM allows activating and obtaining objects from the SCM by CLSID, ProgID, or interface. While efficient for in-process use, COM also specifies marshaling for inter-process communication using remote procedure calls. The definitive references are the COM specification and Essential COM book.

Uploaded by

Anil Dogra
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 27

COM: A Brief Introduction

Dan Berger [email protected]

Outline

A Brief History of COM Objects vs. Components COM as a (C++)++ The What and How of COM COM as CORBA-light The Definitive References

A Brief History of COM

The Brain Child of Anthony Williams outlined in two (internal) MS papers:

Object Architecture: Dealing with the Unknown or Type Safety in a Dynamically Extensible Class (1988) On Inheritance: What It Means and How To Use it (1990)

History (Cont.)

Origins of COM were OLE (Object Linking and Embedding) 1 that shipped with Windows 3.1 (1992) The first public version of COM shipped in OLE 2.0 (1993). DCOM (Distributed COM) was released in 1996 in answer to CORBA. (Well ignore it.) COM+ was released along with Windows 2000 and was primarily concerned with MTS. The DCOM moniker was dropped.

Objects vs. Components

Object Oriented Programming = Polymorphism + (Some) Late Binding + (Some) Encapsulation + Inheritance Component Oriented Programming = Polymorphism + (Really) Late Binding + (Real, Enforced) Encapsulation + Interface Inheritance + Binary Reuse
Charlie Kindel COM Guy Microsoft Corp. 9/97

COM as (C++)++

(Adapted From [2])

If you get this, its all down hill from here. In C++, in particular, the linkage model makes binary distribution and reuse difficult. Consider: Youve written a class thats part of a C++ class library.

Challenges of Distribution

Imagine we distribute the source for the class (as is common in C++ class libraries).

If each application that uses it statically links it, it gets duplicated (waste) and is impossible to update/fix in the field without redistributing a new application. If its packaged as a shared library/object, the lack of binary standardization moves the problem to one of interoperation.

The DLL model (but not the .so model) can actually deal with this lack of standardization, but its not pretty.

Challenges of Encapsulation

Assume we side-step the compiler/linker trouble. The coast still isnt clear. The C++ standard also lacks any standard definition for binary encapsulation. So changes to the internals of an object that dont change its interface can (and do) break code that uses the object.

Consider adding private member variables.

Versioned Libraries

A quick look in /usr/lib or %WINDIR% will likely reveal a number of identical libraries with different versions.

libFoo.so.1 libFoo.so.2

With enough diligence the library developer can insulate applications from change buy explicitly versioning the library.

I think we all agree this is sub-optimal solution.

Interface v. Implementation

C++ supports separation of interface and implementation at the syntax level not at the binary level.

So changes of the implementation are seen by clients.

We could hide the actual implementing class behind an opaque pointer in the interface exposed to the client and delegate interface calls through this pointer to the real object.

Easy for simple, cumbersome for complex interfaces

Abstract Classes as Interfaces

With three assumptions, we can use abstract classes to solve these problems:
1.

2.

3.

C-style structs are represented identically across (C++) compilers. All compilers can be forced to use common call conventions. All compilers on a platform use equivalent virtual call implementations.

vtbls and vptrs

Assumption 3 is critical, and turns out to be not unfounded, as nearly all C++ compilers use vptrs and vtbls. For each class the compiler generates a (static) array of func pointers to its members (its vtbl). Each instance of each class has a (hidden) member that points to the vtbl (its vprt).

Example
class ISearchableString { public: virtual int Length(void) const = 0; virtual int Find(const char *s) = 0; };
vtbl vptr Length (null) Find (null)

IsearchableString

Example (cont.)
class SString : public ISearchableString { public:
SearchableString(const char *s); ~SearchableString(void); int Length(void) const; int Find(const char *s); };
vptr

vtbl

SString::Length SString::Find

SString

Instantiating an Abstract Class

Clearly the client cant instantiate an ISearchableString its pure abstract, nor do we want them instantiating a SString that breaks (binary) encapsulation. So we need a factory method and we can force it (using extern C) to be accessible to all clients.

Virtual Destructors

Unfortunately, theres a problem our class lacks a virtual dtor so calls to delete will use the (default) dtor on the ISearchableString class. We cant add a virtual dtor to the abstract class because different compilers put dtors in different places in the vtbl. (blech) So we add a virtual Delete method to the abstract class.

What is COM

A substrate for building re-usable components. Language neutral

its easier to use in C++, but can be used from any language that can generate/grok vtbls and vptrs. Interfaces are defined in COM IDL (IDL+COM extensions for inheritance and polymorphism) commercial Unix implementations, and MS supports COM on Mac System (OS X?) Using only on the COM spec, we (OMKT) rolled our own.

OS Neutral

Interfaces

Interfaces are uniquely identified by UUIDs (often called GUIDs the terms are equivalent) called their IID (interface ID). Implementers of an interface are uniquely identified by a UUID called their CLSID (class ID). All COM objects implement the IUnknown interface.

IUnknown

Provides three methods:


HRESULT QueryInterface(IID iid, void **ppv) ULONG AddRef(void); ULONG Release(void);

AddRef and Release are for resource management (reference counting). Well mostly ignore them.

QueryInterface

QueryInterface is essentially a run-time cast it allows you to ask a component if it implements a specific interface.

If it does, it returns a pointer to that interface pointer in ppv. Think of it as a compiler/language neutral dynamic_cast operation.

HRESULT

This is language neutral so no exceptions. HRESULTS are a packed bit field return value used all over COM.

Honestly its one of the ugliest parts of COM.

The most used return value is defined as S_OK (success, ok), the other is E_FAIL (error, failure) but there are others. There are macros SUCCEEDED() and FAILED() that take an HRESULT and report success or failure.

Instantiating Objects

So as developers, we have interfaces (defined in IDL) for the components available in a library/on the system. How do we actually obtain an instance of an object we want to use?

In COM this is termed Activation there are three basic types, and each involves the SCM (service control manager).

Activation and the SCM


The SCM manages the mapping between IIDs, CLSIDs, and implementations. You can ask the SCM for a particular CLSID and it will instantiate an instance and return its interface pointer.

CoGetClassObject()

Theres an additional layer of indirection through ProgIDs strings of the form libraryname.classname.version that map to CLSIDs.

Activation (cont.)

Sometimes you want an implementation of the following interface that meets some set of constraints

enter category IDs (CATIDs)

You can define a set of categories, and each COM class can advertise the categories it implements.

COM as CORBA-light

COM provides a very efficient in-process component model.

Once past the initial COCreateInstance and QueryInterface calls, each method call is simply a call-by-func-pointer call, essentially free.

Instantiating a component doesnt require any out of process, or shared memory operations its all DLL (or Shared Object) magic.

Theres Much, Much More

COM is specific about many topics that C++ (and other languages) are not. It specifies:

Execution environment options (so-called Apartments) Inter-process Marshalling Remote Object Activation mechanism and protocols Threading models

The Definitive References


[1] The Component Object Model Specification

Microsoft and Digital Equipment Corp, 1992-1995 www.microsoft.com/com/resources/comdocs.asp Don Box, Addison Wesley ISBN 0-201-63446-5

[2] Essential COM

You might also like