The maturation of the computing industry has some parallels with agri-business, where, in developed nations, a few producers supply the needs of many consumers. One widely accepted view of our computing future is that we will eventually become a community with a few producers (object implementors) supplying many consumers (object users). The consumers will be programmers and power users who will build applications by drawing from a stock of interoperable objects before writing custom code or building custom objects to fill in functionality gaps. The Microsoft contribution to this view of computing with shared objects, or component objects, is Object Linking and Embedding (OLE). [For a complete list of the acronyms used in this article, please see Table 1.]
OLE provides a language-independent, binary standard for object sharing. Before jumping into this technology, you should understand OLE, the Component Object Model (COM), services that build on COM, and OLE custom controls (OCXs). COM is a core technology for creating shareable binary components. It provides the infrastructure upon which OLE layers other software services. COM is a language-independent binary standard that permits object sharing by applications written in a variety of languages. OCXs are Windows controls that provide data-binding capabilities that make them particularly suited to database work. In addition to these technologies, Microsoft has launched an initiative that creates a data integration layer over COM. (See the sidebar,
Microsoft is working on an update to the current OLE 2.0 that will provide interoperable and distributed objects. The company released a revised specification for OLE's COM in March 1995. This specification update discusses distributed objects based on Open Software Foundation's Distributed Computing Environment (DCE) Remote Procedure Calls (RPCs). The COM network protocol is based on the 1994 X/Open DCE RPC Common Applications Environment (CAE) specification. Distributed OLE adds new interfaces related to remote objects, but it is basically an upward extension that shouldn't break existing OLE code.
Microsoft considers OLE a precursor to Cairo, its next-generation operating system that will expose operating system services as objects. Other interoperable object solutions that have become prominent recently include the Object Management Group's Common Object Request Broker Architecture (CORBA), Component Integration Lab's OpenDoc, IBM's System Object Model (SOM), and SunSoft's Distributed Objects Everywhere (DOE). OLE 2.0 has a significant following within the developer community, even
though proponents of other technologies such as OpenDoc and CORBA argue that these solutions are technically superior to OLE. CORBA enjoys support in Unix environments, while OLE has become a de facto object standard for Windows computing.
Some automobile drivers prefer the direct control of a four- or five-speed transmission while others prefer the ease of an automatic transmission. Some programmers work with call-level interfaces (CLIs) such as OSF/DCE or the Windows API; other developers look for object solutions to simplify programming. This latter demographic is the focus for software giants such as IBM and Microsoft, who recognize that capturing the support of this developer group is critical to capturing market share in the 21st century. Object- sharing technology is integral to the architecture of operating systems currently in development.
A developer's choice of programming techniques often involves the level of abstraction at which to operate. Object techniques raise the level of abstraction by encapsulating low- level programming details. For example, a programmer working at a lower level will dig into DCE's 400-plus system calls to use RPCs. A programmer working at a higher level uses a technology such as OLE, which builds on DCE. OLE encapsulates functionality that lets a developer deal with an object without concern for whether the object is local or remote. OLE objects are defined in a registry, so they are usable across applications and available to scripting languages such as Visual Basic for Applications. Microsoft predicts that programming with OLE interfaces will eventually supplant most detail-level programming in Windows and Cairo applications (much as assembly language gave way to higher-level languages).
To understand OLE you should know a few terms and concepts (and a slew of acronyms, as you may have noticed from Table 1). A container is an entity that contains linked or embedded objects. Users of OLE container applications create and manage compound documents that consist of objects from multiple source applications. Objects linked to or embedded within other objects are nested. An application that creates and manages compound documents is a container application. Server applications are object implementors because they create and maintain Windows objects. OLE uses several types of identifiers to define interfaces and object classes uniquely. The universal identifier is the globally unique identifier (GUID), a 128-bit value that provides a unique identity for each interface and object class. OLE also uses a class identifier (CLSID) for every standard object class, and an interface identifier (IID) for every standard interface. Windows Objects are component objects with a unique CLSID. The registration database, or registry, contains the inventory of available objects. It includes a unique CLSID entry for each component object class.
If you understand the rationale for objects, you are probably wondering what services OLE provides to application developers. The short answer is that OLE provides services for object sharing and component integration. The heart of OLE is COM, which is the foundation upon which Microsoft built additional services. Figure 1 shows the various
OLE services, which build on COM. COM provides memory management, error handling, interface negotiation, interprocess communication, and other basic services for component object management. To use OLE, you must install a variety of Windows dynamic link libraries (DLLs), including compobj.dll, the DLL that supports COM.
When you instantiate a component object, you receive a pointer to the object's interface. OLE objects implement one or more interfaces that provide access to an object's member functions but not its data. Figure 2 illustrates multiple interfaces for a single object. The instantiation of an interface is an array of pointers to member functions (the implementation of the interface). An interface is analogous to a C++ abstract base class or a collection of methods. Applications use OLE services by accessing the interfaces defined in Table 2. By calling the interface, a program can obtain a pointer to a table that contains an entry for each function available through that interface. The table is a virtual table (vtable or VTBL) whose entries are themselves pointers to functions.
OLE supports dynamic binding, so you can determine at runtime what functions an interface provides. To support this type of programming, every object implements an interface called IUnknown, which provides a standard member function called QueryInterface. Instead of resolving addresses and type information at link time, an application can obtain this information from QueryInterface at runtime.
All OLE interfaces are derivatives of IUnknown; therefore, every object interface supports QueryInterface. The notation for an OLE call is similar to C++, where you specify a classname::member function. For OLE, you use an interface::member function so that an application that wants to save text to a file would call IPersistFile::Save, where IPersistFile is the interface and Save is the member function (or method).
COM uses a client/server model in which object users are clients and object implementors are servers. In-Process servers execute within the client's address space, while Out-of-Process servers are standalone executables. Clients and servers use a class factory, a feature within the server module that creates objects. Client access to the class factory occurs via the server's IClassFactory interface. COM client applications use the same process to instantiate an object whether the server is In-Process, local, or remote. The client passes a CLSID to COM when instantiating an object. To ask the class factory to manufacture one or more objects, the client obtains the pointer to IClassFactory and calls CoGetClassObject. The client can also call COM's CoCreateInstance to create a single instance (one object).
Marshalling, the process of passing function calls and parameters across process boundaries, handles differences related to different word sizes. It enables objects having 16-bit parameters to interoperate with those having 32-bit parameters. COMPOBJ.DLL contains the marshalling code that resolves addressing differences, so that object users see an object that matches their own address space and has the correct byte ordering.
This action might not be possible to undo. Are you sure you want to continue?