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
Dec 21, 2015
Fundamentals of COM(+)Fundamentals of COM(+)(Part 1)(Part 1)
Don BoxDon BoxDevelopMentorDevelopMentorhttp://www.develop.com/dboxhttp://www.develop.com/dbox
11-20311-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+
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
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
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
// 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
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;}
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?
// 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)
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
// 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
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
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
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!!
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
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
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
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
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
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;}
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
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
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)
// 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
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
// 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
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
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!
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
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
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
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;
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
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
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)
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
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
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
[ 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
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
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
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
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
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
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
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
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!
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