Top Banner
Fundamentals of Fundamentals of COM(+) COM(+) (Part 1) (Part 1) Don Box Don Box DevelopMentor DevelopMentor http://www.develop.com/dbox http://www.develop.com/dbox 11-203 11-203
48
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Fundamentals of COM(+)Fundamentals of COM(+)(Part 1)(Part 1)

Don BoxDon BoxDevelopMentorDevelopMentorhttp://www.develop.com/dboxhttp://www.develop.com/dbox

11-20311-203

Page 2: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

COM – The IdeaCOM – The Idea

COM is based on three fundamental ideasCOM is based on three fundamental ideas– Clients program in terms of interfaces,

not classes– Implementation code is not statically linked, but

rather loaded on-demand at runtime– Object implementors declare their runtime

requirements and the system ensures that these requirements are met

The former two are the core of classic COMThe former two are the core of classic COM The latter is the core of MTS and COM+The latter is the core of MTS and COM+

Page 3: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Tale of Two COMsTale of Two COMs

COM is used primarily for two tasksCOM is used primarily for two tasks Task 1: Gluing together multiple components inside Task 1: Gluing together multiple components inside

a processa process– Class loading, type information, etc

Task 2: Inter-process/Inter-host communicationsTask 2: Inter-process/Inter-host communications– Object-based Remote Procedure Calls (ORPC)

Pros: Same programming model and APIs used for Pros: Same programming model and APIs used for both tasksboth tasks

Cons: Same programming model and APIs used for Cons: Same programming model and APIs used for both tasksboth tasks

Design around the task at handDesign around the task at hand

Page 4: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

MotivationMotivation

We want to build dynamically composable systemsWe want to build dynamically composable systems– Not all parts of application are statically linked

We want to minimize coupling within the systemWe want to minimize coupling within the system– One change propagates to entire source code tree

We want plug-and-play replaceablity and extensibilityWe want plug-and-play replaceablity and extensibility– New pieces should be indistinguishable from old,

known parts

We want freedom from file/path dependenciesWe want freedom from file/path dependencies– xcopy /s *.dll C:\winnt\system32 not a solution

We want components with different runtime We want components with different runtime requirements to live peaceably togetherrequirements to live peaceably together– Need to mix heterogeneous objects in a single process

Page 5: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

A Solution – ComponentsA Solution – Components

Circa-1980’s style object-orientation based on Circa-1980’s style object-orientation based on classes and objectsclasses and objects– Classes used for object implementation– Classes also used for consumer/client type hierarchy

Using class-based OO introduces non-trivial coupling Using class-based OO introduces non-trivial coupling between client and objectbetween client and object– Client assumes complete knowledge of public interface– Client may know even more under certain languages

(e.g., C++) Circa-1990’s object orientation separates client-Circa-1990’s object orientation separates client-

visible type system from object-visible visible type system from object-visible implementationimplementation– Allows client to program in terms of abstract types– When done properly, completely hides implementation class

from client

Page 6: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

// faststring.h – seen by client and object implementorclass FastString { char* m_psz;public: FastString(const char* psz); ~FastString(); int Length() const; int Find(const char* pszSearchString) const; };

// faststring.cpp – seen by object implementor onlyFastString::FastString(const char* psz) : : :

Recall: Class-Based OOPRecall: Class-Based OOP

The object implementor defines a class that…The object implementor defines a class that…– Is used to produce new objects– Is used by the client to instantiate and invoke methods

Page 7: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Recall: Class-Based OOPRecall: Class-Based OOP

Client expected to import full definition of classClient expected to import full definition of class– Includes complete public signature at time of compilation– Also includes size/offset information under C++

// client.cpp // import type definitions to use object#include “faststring.h”int FindTheOffset( ) { int i = -1; FastString* pfs = new FastString(“Hello, World!”); if (pfs) { i = pfs->Find(“o, W”); delete pfs; } return i;}

Page 8: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Class-Based OO PitfallsClass-Based OO Pitfalls

Classes not Classes not soso bad when the world is statically linkedbad when the world is statically linked– Changes to class and client happen simultaneously – Problematic if existing public interface changes…

Most environments do a poor job at distinguishing Most environments do a poor job at distinguishing changes to public interface from private detailschanges to public interface from private details– Touching private members usually triggers cascading rebuild

Static linking has many drawbacksStatic linking has many drawbacks– Code size bigger– Can’t replace class code independently

Open Question:Open Question: Can classes be dynamically linked?Can classes be dynamically linked?

Page 9: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

// faststring.h

class __declspec(dllexport) FastString { char* m_psz;public: FastString(const char* psz); ~FastString(); int Length() const; int Find(const char* pszSearchString) const; };

Classes Versus Dynamic LinkingClasses Versus Dynamic Linking

Most compilers offer a compiler keyword or directive to Most compilers offer a compiler keyword or directive to export all class members from DLLexport all class members from DLL– Results in mechanical change at build/run-time– Requires zero change to source code (except introducing the

directive)

Page 10: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Classes Versus Dynamic LinkingClasses Versus Dynamic Linking

Client AClient A Clients statically link to Clients statically link to import libraryimport library– Maps symbolic name to

DLL and entry name Client imports resolved at Client imports resolved at

load timeload time Note: C++ compilers non-Note: C++ compilers non-

standard wrt DLLsstandard wrt DLLs– DLL and clients must be

built using same compiler/linker

Client BClient B

Client CClient C

faststring.dllfaststring.dll

import nameimport name file namefile name export nameexport name

??@3fFastString_6Length??@3fFastString_6Length??@3fFastString_4Find??@3fFastString_4Find??@3fFastString_ctor@sz2??@3fFastString_ctor@sz2??@3fFastString_dtor??@3fFastString_dtor

faststring.dllfaststring.dllfaststring.dllfaststring.dllfaststring.dllfaststring.dllfaststring.dllfaststring.dll

??@3fFastString_6Length??@3fFastString_6Length??@3fFastString_4Find??@3fFastString_4Find??@3fFastString_ctor@sz2??@3fFastString_ctor@sz2??@3fFastString_dtor??@3fFastString_dtor

faststring.lib

Page 11: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

// faststring.hclass FastString { char* m_psz;public: FastString(const char* psz); ~FastString(); int Length() const; int Find(const char* pszSearchString) const; };

// faststring.cpp#include “faststring.h”#include <string.h>

int FastString::Length() const { return strlen(m_psz);}

Classes Versus Dynamic Linking: Classes Versus Dynamic Linking: EvolutionEvolution

Challenge: Improve the performance of Length!Challenge: Improve the performance of Length!– Do not change public

interface and breakencapsulation

Page 12: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

class __declspec(dllexport) FastString{ char* m_psz; int m_len;public: FastString(const char* psz); ~FastString(); int Length() const; int Find(const char* pszSS) const; };

FastString::FastString(const char* sz): m_psz(new char[strlen(sz)+1]), m_len(strlen(sz)) { strcpy(m_psz, sz);} int FastString::Length() const { return m_len;}

Classes Versus Dynamic Linking: Classes Versus Dynamic Linking: EvolutionEvolution

Solution: Speed up FastString::Length by Solution: Speed up FastString::Length by caching length as data membercaching length as data member

Page 13: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Client AClient A

Client BClient B

Client CClient C

faststring.dllfaststring.dll

sizeof==8sizeof==8

sizeof==8sizeof==8sizeof==4sizeof==4

sizeof==4sizeof==4

Classes Versus Dynamic Linking: Classes Versus Dynamic Linking: EvolutionEvolution

New DLL assumes New DLL assumes sizeof(FastString) is 8sizeof(FastString) is 8

Existing Clients assume Existing Clients assume sizeof(FastString) is 4sizeof(FastString) is 4

Clients that want new Clients that want new functionality recompile functionality recompile

Old Clients break!Old Clients break! This is an inherent limitation This is an inherent limitation

of virtually all C++ of virtually all C++ environmentsenvironments

Page 14: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Client AClient A(v2)(v2)

faststring.dllfaststring.dll(v1)(v1)

FastString::FastStringFastString::FastStringFastString::~FastStringFastString::~FastStringFastString::LengthFastString::LengthFastString::FindFastString::Find

FastString::FastStringFastString::FastStringFastString::~FastStringFastString::~FastString

FastString::LengthFastString::LengthFastString::FindFastString::FindFastString::FindNFastString::FindN

Classes Versus Dynamic Linking: Classes Versus Dynamic Linking: Interface EvolutionInterface Evolution

Adding new public methods OK when statically linkedAdding new public methods OK when statically linked– Class and client code inseparable

Adding public methods to a DLL-based class dangerous!Adding public methods to a DLL-based class dangerous!– New client expects method to be there

– Old DLLs have never heard of this method!!

Page 15: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

ConclusionsConclusions

Cannot change definition of a data type Cannot change definition of a data type without massive rebuild/redeployment of without massive rebuild/redeployment of client/objectclient/object

If clients program in terms of classes, If clients program in terms of classes, then classes cannot change in any then classes cannot change in any meaningful waymeaningful way

Classes must change because we can’t Classes must change because we can’t get it right the first timeget it right the first time

Solution: Clients must not programSolution: Clients must not programin terms of classesin terms of classes

Page 16: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Interface-Based ProgrammingInterface-Based Programming

Key to solving the replaceable component problem Key to solving the replaceable component problem is to split the world into twois to split the world into two

The types the client programs against can never The types the client programs against can never changechange– Since classes need to change, these better not be classes!

Solution based on defining alternative type system Solution based on defining alternative type system based on abstract types called interfacesbased on abstract types called interfaces

Allowing client to only see interfaces insulates Allowing client to only see interfaces insulates clients from changes to underlying class hierarchyclients from changes to underlying class hierarchy

Most common C++ technique for bridging interfaces Most common C++ technique for bridging interfaces and classes is to use abstract baseand classes is to use abstract baseclasses as interfacesclasses as interfaces

Page 17: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Abstract Bases As InterfacesAbstract Bases As Interfaces

A class can be designated as abstract by making A class can be designated as abstract by making (at least) one method(at least) one method pure virtual pure virtual

struct IFastString {

virtual int Length() const = 0;

virtual int Find(const char*) const = 0;

};

Cannot instantiate abstract baseCannot instantiate abstract base– Can declare pointers or references to abstract bases

Must instead derive concrete type that implements Must instead derive concrete type that implements each pure virtual functioneach pure virtual function

Classes with Classes with only only pure virtual functions (no data pure virtual functions (no data members, no implementation code) often called members, no implementation code) often called pure pure abstract bases, protocol classesabstract bases, protocol classes or or interfaces interfaces

Page 18: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Interfaces And ImplementationsInterfaces And Implementations

Given an abstract interface, the most common Given an abstract interface, the most common way to associate an implementation with it isway to associate an implementation with it isthrough inheritancethrough inheritance

class FastString : public IFastString {...}; Implementation type must provide concrete Implementation type must provide concrete

implementations of each interface methodimplementations of each interface method Some mechanism needed to create instances Some mechanism needed to create instances

of the implementation type without exposing of the implementation type without exposing layoutlayout– Usually takes the form of a creator or factory

function Must provide client with a way to delete objectMust provide client with a way to delete object– Since the new operator is not used by the client, it

cannot call the delete operator

Page 19: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Exporting Via Abstract BasesExporting Via Abstract Bases

// faststringclient.h – common header between client/class

// here’s the DLL-friendly abstract interface:struct IFastString { virtual void Delete() = 0; virtual int Length() const = 0; virtual int Find(const char* sz) const = 0;};

// and here’s the DLL-friendly factory function:extern “C” boolCreateInstance(const char* pszClassName, // which class? const char* psz, // ctor args IFastString** ppfs); // the objref

Page 20: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Exporting Via Abstract BasesExporting Via Abstract Bases// faststring.h – private source file of class#include “faststringclient.h”class FastString : public IFastString {// normal prototype of FastString class + Delete void Delete() { delete this; }};

// component.cpp – private source file for entire DLL#include “faststring.h” // import FastString#include “fasterstring.h” // import FasterString (another class)

bool CreateInstance(const char* pszClassName, const char* psz, IFastString** ppfs) { *ppfs = 0; if (strcmp(pszClassName, “FastString”) == 0) *ppfs = static_cast<IFastString*>(new FastString(sz)); else if (strcmp(pszClassName, “FasterString”) == 0) *ppfs = static_cast<IFastString*>(new FasterString(sz)); return *ppfs != 0;}

Page 21: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

m_textm_text

m_lengthm_length

vptrvptr FastString::DeleteFastString::Delete

FastString::LengthFastString::Length

FastString::FindFastString::Find

pfspfs

ClientClient ObjectObject

Exporting Using Abstract BasesExporting Using Abstract Bases

Page 22: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

bool LoadAndCreate(const char* szDLL, const char* sz, IFastString** ppfs){ HINSTANCE h = LoadLibrary(szDLL); bool (*fp)(const char*, const char*, IFastString**); *((FARPROC*)&fp) = GetProcAddress(h, “CreateInstance”); return fp(“FastString”, sz, ppfs);}

Interfaces And Plug-compatibilityInterfaces And Plug-compatibility

Note that a particular DLL can supply multiple implementations Note that a particular DLL can supply multiple implementations of same interfaceof same interface

CreateInstance(“SlowString”, “Hello!!”, &pfs); Due to simplicity of model, runtime selection ofDue to simplicity of model, runtime selection of

implementation trivialimplementation trivial– Explicitly load DLL and bind function address

Page 23: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Interfaces And EvolutionInterfaces And Evolution

Previous slides alluded to interface remaining Previous slides alluded to interface remaining constant across versionsconstant across versions

Interface-based development mandates that new Interface-based development mandates that new functionality be exposed using additional interface functionality be exposed using additional interface – Extended functionality provided by deriving from

existing interface– Orthogonal functionality provided by creating new

sibling interface

Some technique needed for dynamically interrogating Some technique needed for dynamically interrogating an object for interface supportan object for interface support– Most languages support some sort of runtime cast operation

(e.g., C++’s dynamic_cast)

Page 24: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

// faststringclient.hstruct IFastNFind : public IFastString { virtual int FindN(const char* sz, int n) const = 0;};

// faststringclient.cxx

int Find10thInstanceOfFoo(IFastString* pfs) { IFastNFind* pfnf = 0; if (pfnf = dynamic_cast<IFastNFind*>(pfs)) return pfnf->FindN(“Foo”, 10); else // implement by hand...}

Example: Adding Extended FunctionalityExample: Adding Extended Functionality

Add method to find the nth instance of szAdd method to find the nth instance of sz

Page 25: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

m_textm_text

m_lengthm_length

vptrvptr

FastString::DeleteFastString::Delete

FastString::LengthFastString::Length

FastString::FindFastString::Find

pfspfs

ClientClient ObjectObject

pfnfpfnfFastString::FindNFastString::FindN

Example: Adding Extended FunctionalityExample: Adding Extended Functionality

Page 26: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

// faststringclient.hstruct IPersistentObject { virtual void Delete(void) = 0; virtual bool Load(const char* sz) = 0; virtual bool Save(const char* sz) const = 0;};

// faststringclient.cxx

bool SaveString(IFastString* pfs) { IPersistentObject* ppo = 0; if (ppo = dynamic_cast<IPersistentObject*>(pfs)) return ppo->Save(“Autoexec.bat”); else return false; // cannot save...}

Example: Adding Orthogonal FunctionalityExample: Adding Orthogonal Functionality

Add support for generic persistenceAdd support for generic persistence

Page 27: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

m_textm_text

m_lengthm_length

vptrvptr

FastString::DeleteFastString::Delete

FastString::LengthFastString::Length

FastString::FindFastString::Find

pfspfs

Client Object

vptrvptr

FastString::DeleteFastString::Delete

FastString::LoadFastString::Load

ppoppo

FastString::SaveFastString::Save

Example: Adding Orthogonal FunctionalityExample: Adding Orthogonal Functionality

Page 28: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Fixing Interface-Based Programming In C++Fixing Interface-Based Programming In C++

The dynamic_cast operator has several problems that The dynamic_cast operator has several problems that must be addressedmust be addressed– 1) Its implementation is non-standard across compilers– 2) There is no standard runtime representation

for the typename– 3) Two parties may choose colliding typenames

Can solve #1 by adding yet another well-known Can solve #1 by adding yet another well-known abstract method to each interface (a la Delete)abstract method to each interface (a la Delete)

#2 and #3 solved by using a well-known #2 and #3 solved by using a well-known namespace/type format for identifying interfacesnamespace/type format for identifying interfaces– UUIDs from OSF DCE are compact (128 bit), efficient and

guarantee uniqueness– UUIDs are basically big, unique integers!

Page 29: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

QueryInterfaceQueryInterface

COM programmers use the well-known abstract COM programmers use the well-known abstract method (QueryInterface) in lieu of dynamic_castmethod (QueryInterface) in lieu of dynamic_cast

virtual HRESULT _stdcall

QueryInterface(REFIID riid,// the requested UUID

void** ppv // the resultant objref

) = 0;

Returns status code indicating success (S_OK) or Returns status code indicating success (S_OK) or failure (E_NOINTERFACE)failure (E_NOINTERFACE)

UUID is integral part of interface definitionUUID is integral part of interface definition– Defined as a variable with IID_ prefixed to type name– VC-specific __declspec(uuid) conjoins COM/C++ names

Page 30: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

void UseAsTelephone(ICalculator* pCalc) { ITelephone* pPhone = 0; pPhone = dynamic_cast<ITelephone*>(pCalc); if (pPhone) { // use pPhone : : :

void UseAsTelephone(ICalculator* pCalc) { ITelephone* pPhone = 0; HRESULT hr = pCalc->QueryInterface(IID_ITelephone, (void**)&pPhone); if (hr == S_OK) { // use pPhone : : :

QueryInterface As A Better Dynamic CastQueryInterface As A Better Dynamic Cast

Page 31: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

ICalculator* pCalc1 = CreateCalc();ITelephone* pPhone1 = CreatePhone();ICalculator* pCalc2 = dynamic_cast<ICalculator*>(pPhone1);ICalculator* pCalc3 = CreateCalc();

pPhone1->Dial(pCalc1->Add(pCalc2->Add(pCalc3->Add(2))));

pCalc1->Delete(); // assume interfaces have Delete pCalc2->Delete(); // per earlier discussionpPhone1->Delete();

Fixing Interface-Based Programming In C++Fixing Interface-Based Programming In C++

Previous examples used a “Delete” method to allow Previous examples used a “Delete” method to allow client to destroy objectclient to destroy object– Requires client to remember which references point to which

objects to ensure each object deleted exactly once

Page 32: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Fixing Interface-Based Programming In C++Fixing Interface-Based Programming In C++

COM solves the “Delete” problem withCOM solves the “Delete” problem withreference countingreference counting– Clients blindly “Delete” each reference, not each object

Objects can track number of extant references and Objects can track number of extant references and auto-delete when count reaches zeroauto-delete when count reaches zero– Requires 100% compliance with ref. counting rules

All operations that return interface pointers must All operations that return interface pointers must increment the interface pointer’s reference countincrement the interface pointer’s reference count– QueryInterface, CreateInstance, etc.

Clients must inform object that a particular interface Clients must inform object that a particular interface pointer has been destroyed using well-known methodpointer has been destroyed using well-known method– Virtual ULONG _stdcall Release() = 0;

Page 33: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

ICalculator* pCalc1 = CreateCalc();ITelephone* pPhone1 = CreatePhone();ICalculator* pCalc2 = 0;ICalculator* pCalc3 = CreateCalc();ITelephone * pPhone2 = 0;ICalculator* pCalc4 = 0;

pPhone1->QueryInterface(IID_ICalculator,(void**)&pCalc2);pCalc3->QueryInterface(IID_ITelephone,(void**)&pPhone2);pCalc1->QueryInterface(IID_ICalculator, (void**)&pCalc4);

pPhone1->Dial(pCalc1->Add(pCalc2->Add(pCalc3->Add(2))));

pCalc1->Release(); pCalc4->Release(); pCalc2->Release(); pPhone1->Release(); pCalc3->Release(); pPhone2->Release();

Reference Counting BasicsReference Counting Basics

Page 34: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

extern const IID IID_IUnknown;struct IUnknown { virtual HRESULT STDMETHODCALLTYPE QueryInterface( const IID& riid, void** ppv) = 0; virtual ULONG STDMETHODCALLTYPE AddRef() = 0; virtual ULONG STDMETHODCALLTYPE Release() = 0;};

IUnknownIUnknown

The three core abstract operations (QueryInterface, The three core abstract operations (QueryInterface, AddRef, and Release) comprise the core interfaceAddRef, and Release) comprise the core interfaceof COM, IUnknownof COM, IUnknown

All COM interfaces must extend IUnknownAll COM interfaces must extend IUnknown All COM objects must implement IUnknownAll COM objects must implement IUnknown

Page 35: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Com Interfaces In NatureCom Interfaces In Nature

Represented as pure abstract baseRepresented as pure abstract baseclasses in C++classes in C++– All methods are pure virtual– Never any code, only signature– Format of C++ vtable/vptr defines expected stack frame

Represented directly as interfaces in JavaRepresented directly as interfaces in Java Represented as Non-Creatable classes inRepresented as Non-Creatable classes in

Visual BasicVisual Basic Uniform binary representation independent of how Uniform binary representation independent of how

you built the objectyou built the object Identified uniquely by a 128-bit Interface ID (IID)Identified uniquely by a 128-bit Interface ID (IID)

Page 36: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Com Interfaces In NatureCom Interfaces In Nature

COM interfaces are described first inCOM interfaces are described first inCOM IDLCOM IDL

COM IDL is an extension to DCE IDLCOM IDL is an extension to DCE IDL– Support for objects + various wire optimizations

IDL compiler directly emits C/C++ interface IDL compiler directly emits C/C++ interface definitions as source codedefinitions as source code

IDL compiler emits tokenized type library IDL compiler emits tokenized type library containing (most) of original contents in an containing (most) of original contents in an easily parsed formateasily parsed format

JavaJava™™/Visual Basic/Visual Basic®® pick up mappings from pick up mappings from type librarytype library

Page 37: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Foo.idlFoo.idlIDLIDL

DescriptionDescriptionof Foo interfacesof Foo interfaces

and datatypesand datatypes

Foo.hFoo.hC/C++C/C++

DefinitionsDefinitions

Foo_i.cFoo_i.cGUIDsGUIDs

Foo_p.cFoo_p.cProxy/StubProxy/Stub

dlldata.cdlldata.cClass LoadingClass Loading

SupportSupport

Foo.tlbFoo.tlbBinary Binary

DescriptionsDescriptions

MIDL.EXEMIDL.EXE *.java*.javaJava Java

DefinitionsDefinitions

JACTIVEX.EXEJACTIVEX.EXE

COM IDLCOM IDL

Page 38: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

COM IDLCOM IDL

All elements in an IDL file can have attributesAll elements in an IDL file can have attributes– Appear in [ ] prior to subject of attributes

Interfaces are defined at global scopeInterfaces are defined at global scope– Required by MIDL to emit networking code

Must refer to exported types inside library blockMust refer to exported types inside library block– Required by MIDL to emit type library definition

Can import std interface suiteCan import std interface suite• WTYPES.IDL - basic data types

• UNKNWN.IDL - core type interfaces

• OBJIDL.IDL - core infrastructure itfs

• OLEIDL.IDL - OLE itfs

• OAIDL.IDL - Automation itfs

• OCIDL.IDL - ActiveX Control itfs

Page 39: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

[ uuid(DEFACED1-0229-2552-1D11-ABBADABBAD00), object ]interface ICalculator : IDesktopDevice { import “dd.idl”; // bring in IDesktopDevice HRESULT Clear(void); HRESULT Add([in] short n); // n sent to object HRESULT GetSum([out] short* pn); // *pn sent to caller}[ uuid(DEFACED2-0229-2552-1D11-ABBADABBAD00), helpstring(“My Datatypes”) ]library CalcTypes { importlib(“stdole32.tlb”); // required interface ICalculator; // cause TLB inclusion}

CalcTypes.idlCalcTypes.idl

COM IDLCOM IDL

Page 40: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

COM IDL - C++ MappingCOM IDL - C++ Mapping

#include “dd.h”extern const IID IID_ICalculator;struct __declspec(uuid(“DEFACED1-0229-2552-1D11-ABBADABBAD00”)) ICalculator : public IDesktopDevice { virtual HRESULT STDMETHODCALLTYPE Clear(void) = 0; virtual HRESULT STDMETHODCALLTYPE Add(short n) = 0; virtual HRESULT STDMETHODCALLTYPE GetSum(short* pn) = 0;};extern const GUID LIBID_CalcTypes;

const IID IID_ICalculator = {0xDEFACED1, 0x0229, 0x2552, { 0x1D, 0x11, 0xAB, 0xBA, 0xDA, 0xBB, 0xAD, 0x00 } };const GUID LIBID_CalcTypes = {0xDEFACED2, 0x0229, 0x2552, { 0x1D, 0x11, 0xAB, 0xBA, 0xDA, 0xBB, 0xAD, 0x00 } };

CalcTypes.h

CalcTypes_i.c

Page 41: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

COM IDL – Java/VB MappingCOM IDL – Java/VB Mapping

package CalcTypes; // library name/**@com.interface(iid=DEFACED1-0229-2552-1D11-ABBADABBAD00)*/interface ICalculator extends IDesktopDevice { public void Clear( ); public void Add(short n); public void GetSum(short [] pn); // array of length 1 public static com.ms.com._Guid iid = new com.ms.com._Guid(0xDEFACED1, 0x0229, 0x2552, 0x1D, 0x11, 0xAB, 0xBA, 0xDA, 0xBB, 0xAD, 0x00);}

CalcTypes.javaCalcTypes.java

Public Sub Clear( )Public Sub Add(ByVal n As Integer)Public Sub GetSum(ByRef pn As Integer)

CalcTypes.clsCalcTypes.cls

Page 42: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

particular valueparticular valueresres

Severity (31)Severity (31) Facility (27-16)Facility (27-16) Code (15-0)Code (15-0)

0 -> Success0 -> Success1 -> Failure1 -> Failure

FACILITY_NULLFACILITY_NULLFACILITY_ITFFACILITY_ITFFACILITY_STORAGEFACILITY_STORAGEFACILITY_DISPATCHFACILITY_DISPATCHFACILITY_WINDOWSFACILITY_WINDOWSFACILITY_RPCFACILITY_RPC

COM And Error HandlingCOM And Error Handling

COM doesn’t support typed C++ or Java-style COM doesn’t support typed C++ or Java-style exceptionsexceptions

All (remotable) methods must return a standard 32-bit All (remotable) methods must return a standard 32-bit error code called an HRESULTerror code called an HRESULT– Mapped to exception in higher-level languages– Overloaded to indicate invocation errors from proxies

Page 43: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

HRESULTsHRESULTs

HRESULT names indicate severity and facilityHRESULT names indicate severity and facility• <FACILITY>_<SEVERITY>_<CODE>• DISP_E_EXCEPTION• STG_S_CONVERTED

FACILITY_NULL codes are implicitFACILITY_NULL codes are implicit• <SEVERITY>_<CODE>• S_OK• S_FALSE• E_FAIL• E_NOTIMPL• E_OUTOFMEMORY• E_INVALIDARG• E_UNEXPECTED

Can use FormatMessage API to lookup human-readable Can use FormatMessage API to lookup human-readable description at runtimedescription at runtime

Page 44: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

smallsmall

longlong

hyperhyper

IDLIDL C++C++ JavaJava

shortshort

charchar

longlong

__int64__int64

bytebyte

intint

longlong

shortshort shortshort

Visual BasicVisual Basic

N/AN/A

LongLong

N/AN/A

IntegerInteger

unsigned smallunsigned small

unsigned longunsigned long

unsigned hyperunsigned hyper

unsigned shortunsigned short

unsigned charunsigned char

unsigned longunsigned long

unsigned __int64unsigned __int64

bytebyte

intint

longlong

unsigned shortunsigned short shortshort

ByteByte

N/AN/A

N/AN/A

N/AN/A

floatfloat

doubledouble

floatfloat

doubledouble

floatfloat

doubledouble

SingleSingle

DoubleDouble

charchar

unsigned charunsigned char

charchar

unsigned charunsigned char

charchar

bytebyte

N/AN/A

ByteByte

wchar_twchar_t wchar_twchar_t charchar IntegerInteger

ScriptScript

NoNo

YesYes

NoNo

YesYes

NoNo

NoNo

NoNo

NoNo

YesYes

YesYes

NoNo

YesYes

NoNo

COM Data TypesCOM Data Types

Page 45: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

bytebyte

booleanboolean

VARIANT_BOOLVARIANT_BOOL

IDLIDL C++C++ JavaJava

BYTEBYTE

unsigned charunsigned char

longlong

VARIANT_BOOLVARIANT_BOOL

charchar

intint

booleanboolean

unsigned charunsigned char bytebyte

Visual BasicVisual Basic

N/AN/A

LongLong

BooleanBoolean

ByteByte

BSTRBSTR

VARIANTVARIANT

BSTRBSTR java.lang.Stringjava.lang.String

VARIANTVARIANT com.ms.com.Variantcom.ms.com.Variant

StringString

VariantVariant

CYCY longlong intint CurrencyCurrency

DATEDATE

enumenum

doubledouble doubledouble

enumenum intint

DateDate

EnumEnum

Typed ObjRefTyped ObjRef IFoo *IFoo * interface IFoointerface IFoo IFooIFoo

structstruct structstruct final classfinal class TypeType

unionunion

C-style ArrayC-style Array

unionunion N/AN/A

arrayarray arrayarray

N/AN/A

N/AN/A

ScriptScript

NoNo

NoNo

YesYes

YesYes

YesYes

YesYes

YesYes

YesYes

YesYes

YesYes

NoNo

NoNo

NoNo

COM Data TypesCOM Data Types

Page 46: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

struct MESSAGE { VARIANT_BOOL b; long n; };[ uuid(03C20B33-C942-11d1-926D-006008026FEA), object ]interface IAnsweringMachine : IUnknown { HRESULT TakeAMessage([in] struct MESSAGE* pmsg); [propput] HRESULT OutboundMessage([in] long msg); [propget] HRESULT OutboundMessage([out, retval] long* p);}

public final class MESSAGE { public boolean b; public int n; }public interface IAnsweringMachine extends IUnknown { public void TakeAMessage(MESSAGE msg); public void putOutboundMessage(int); public int getOutboundMessage();}

ExampleExample

Page 47: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

Where Are We?Where Are We?

Clients program in terms of abstract data Clients program in terms of abstract data types called interfacestypes called interfaces

Clients can load method code dynamically Clients can load method code dynamically without concern for C++ compiler without concern for C++ compiler incompatibilitiesincompatibilities

Clients interrogate objects for extended Clients interrogate objects for extended functionality via RTTI-like constructsfunctionality via RTTI-like constructs

Clients notify objects when references are Clients notify objects when references are duplicated or destroyedduplicated or destroyed

Welcome to the Component Object Model!Welcome to the Component Object Model!

Page 48: Fundamentals of COM(+) (Part 1) Don Box DevelopMentor  11-203.

ReferencesReferences

Programming Dist Apps With Visual Basic Programming Dist Apps With Visual Basic and COMand COM– Ted Pattison, Microsoft Press

Inside COMInside COM– Dale Rogerson, Microsoft Press

Essential COM(+), 2nd Edition (the book)Essential COM(+), 2nd Edition (the book)– Don Box, Addison Wesley Longman (4Q99)

Essential COM(+) Short Course, Essential COM(+) Short Course, DevelopMentorDevelopMentor– http://www.develop.com

DCOM Mailing ListDCOM Mailing List– http://discuss.microsoft.com