• Non ci sono risultati.

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

N/A
N/A
Protected

Academic year: 2021

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

Copied!
50
0
0

Testo completo

(1)

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

(2)

COM – The Idea COM – The Idea

Classic COM is based on two fundamental Classic COM is based on two fundamental ideas

ideas

– Clients program in terms of interfaces, not classes

– Implementation code is not statically linked, but rather loaded on-demand at runtime

(3)

Tale of Two COMs Tale 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 process

a 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 tasks

both tasks

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

both tasks

Design around the task at handDesign around the task at hand

(4)

Motivation Motivation

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 together

requirements to live peaceably together

– Need to mix heterogeneous objects in a single process

(5)

A Solution – Components A Solution – Components

Circa-1980’s style object-orientation based on classes Circa-1980’s style object-orientation based on classes and objects

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 object

between 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-visible Circa-1990’s object orientation separates client-visible type system from object-visible implementation

type system from object-visible implementation

– Allows client to program in terms of abstract types

– When done properly, completely hides implementation class from client

(6)

COM Usage COM Usage

Partly superseded by .Net Partly superseded by .Net

Still used as part of Windows Still used as part of Windows

Runtime (Windows 8 and later)

Runtime (Windows 8 and later)

(7)

// faststring.h – seen by client and object implementor class 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 only FastString::FastString(const char* psz)

: : :

Recall: Class-Based OOP Recall: 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

(8)

Recall: Class-Based OOP Recall: 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;

}

(9)

Class-Based OO Pitfalls Class-Based OO Pitfalls

Classes not soClasses not so 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 details

changes 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?

(10)

// 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 Linking Classes 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 DLL

export all class members from DLL

– Results in mechanical change at build/run-time

– Requires zero change to source code (except introducing the directive)

(11)

Classes Versus Dynamic Classes Versus Dynamic

Linking

Linking

Client AClient A

Clients statically link to Clients statically link to import library

import library

– Maps symbolic name to DLL and entry name

Client imports resolved at Client imports resolved at load time

load time

Note: C++ compilers non-Note: C++ compilers non- standard wrt DLLs

standard wrt DLLs

– DLL and clients must be built using same

compiler/linker

Client B Client B

Client C Client C

faststring.dll faststring.dll

import name

import 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.dll faststring.dll faststring.dll faststring.dll faststring.dll faststring.dll faststring.dll faststring.dll

??@3fFastString_6Length

??@3fFastString_6Length

??@3fFastString_4Find

??@3fFastString_4Find

??@3fFastString_ctor@sz2

??@3fFastString_ctor@sz2

??@3fFastString_dtor

??@3fFastString_dtor

faststring.lib

(12)

// faststring.h class 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 Classes Versus Dynamic

Linking: Evolution Linking: Evolution

Challenge: Improve the performance of Length!Challenge: Improve the performance of Length!

– Do not change public interface and break encapsulation

(13)

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 Classes Versus Dynamic

Linking: Evolution Linking: Evolution

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

caching length as data member

(14)

Client A Client A

Client B Client B

Client C Client C

faststring.dll faststring.dll

sizeof==8 sizeof==8

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

sizeof==4

sizeof==4 sizeof==4

Classes Versus Dynamic Classes Versus Dynamic

Linking: Evolution Linking: Evolution

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

Existing Clients assume Existing Clients assume sizeof(FastString) is 4 sizeof(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 of This is an inherent limitation of virtually all C++ environments virtually all C++ environments

(15)

Client A Client A

(v2)(v2) faststring.dllfaststring.dll (v1)(v1)

FastString::FastString FastString::FastString FastString::~FastString FastString::~FastString FastString::Length

FastString::Length FastString::Find FastString::Find FastString::FastString

FastString::FastString FastString::~FastString FastString::~FastString FastString::Length FastString::Length FastString::Find FastString::Find FastString::FindN FastString::FindN

Classes Versus Dynamic Linking:

Classes Versus Dynamic Linking:

Interface Evolution Interface 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!!

(16)

Conclusions Conclusions

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/object client/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 way

meaningful way

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

get it right the first time

Solution: Clients must not program Solution: Clients must not program in terms of classes

in terms of classes

(17)

Interface-Based Programming Interface-Based Programming

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

is to split the world into two

The types the client programs against can never The types the client programs against can never change

change

– 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 interfaces

based 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 hierarchy clients 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 base

and classes is to use abstract base classes as interfaces

classes as interfaces

(18)

Abstract Bases As Interfaces Abstract 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 function

each pure virtual function

Classes with only Classes with 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 classes

abstract bases, protocol classes or interfaces or interfaces

(19)

Interfaces And Interfaces And

Implementations Implementations

Given an abstract interface, the most common Given an abstract interface, the most common way to associate an implementation with it is way to associate an implementation with it is through inheritance

through inheritance

class FastString : public IFastString {...};

Implementation type must provide concrete Implementation type must provide concrete implementations of each interface method implementations 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 layout

layout

– Usually takes the form of a creator or factory function

Must provide client with a way to delete object Must provide client with a way to delete object

– Since the new operator is not used by the client, it cannot call the delete operator

(20)

Exporting Via Abstract Bases Exporting 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” bool

CreateInstance(const char* pszClassName, // which class?

const char* psz, // ctor args IFastString** ppfs); // the objref

(21)

Exporting Via Abstract Bases Exporting 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;

}

(22)

m_text m_text m_length m_length

vptrvptr FastString::DeleteFastString::Delete FastString::Length FastString::Length

FastString::Find FastString::Find pfspfs

Client

Client ObjectObject

Exporting Using Abstract Exporting Using Abstract

Bases

Bases

(23)

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- Interfaces And Plug-

compatibility compatibility

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

of same interface

CreateInstance(“SlowString”, “Hello!!”, &pfs);

Due to simplicity of model, runtime selection ofDue to simplicity of model, runtime selection of implementation trivial

implementation trivial

– Explicitly load DLL and bind function address

(24)

Interfaces And Evolution Interfaces And Evolution

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

constant 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 support

an object for interface support

– Most languages support some sort of runtime cast operation (e.g., C++’s dynamic_cast)

(25)

// faststringclient.h

struct 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 Example: Adding Extended

Functionality Functionality

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

(26)

m_text m_text m_length m_length

vptrvptr

FastString::Delete FastString::Delete FastString::Length FastString::Length

FastString::Find FastString::Find pfspfs

Client

Client ObjectObject

pfnfpfnf

FastString::FindN FastString::FindN

Example: Adding Extended Example: Adding Extended

Functionality

Functionality

(27)

// faststringclient.h

struct 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 Functionality Example: Adding Orthogonal Functionality

Add support for generic persistence Add support for generic persistence

(28)

m_text m_text m_length m_length

vptrvptr

FastString::Delete FastString::Delete FastString::Length FastString::Length

FastString::Find FastString::Find pfspfs

Client Object

vptrvptr

FastString::Delete FastString::Delete

FastString::Load FastString::Load ppoppo

FastString::Save FastString::Save

Example: Adding Orthogonal Functionality

Example: Adding Orthogonal Functionality

(29)

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 addressed

must 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 interfaces namespace/type format for identifying interfaces

– UUIDs from OSF DCE are compact (128 bit), efficient and guarantee uniqueness

– UUIDs are basically big, unique integers!

(30)

QueryInterface QueryInterface

COM programmers use the well-known abstract COM programmers use the well-known abstract method (QueryInterface) in lieu of dynamic_cast method (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

(31)

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 Cast

QueryInterface As A Better Dynamic Cast

(32)

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 discussion

pPhone1->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 object

client to destroy object

– Requires client to remember which references point to which objects to ensure each object deleted exactly once

(33)

Fixing Interface-Based Programming In C++

Fixing Interface-Based Programming In C++

COM solves the “Delete” problem withCOM solves the “Delete” problem with reference counting

reference 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 zero

auto-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 count increment 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 method pointer has been destroyed using well-known method

– Virtual ULONG _stdcall Release() = 0;

(34)

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 Basics

Reference Counting Basics

(35)

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;

};

IUnknown IUnknown

The three core abstract operations (QueryInterface, The three core abstract operations (QueryInterface, AddRef, and Release) comprise the core interface AddRef, and Release) comprise the core interface of COM, IUnknown

of COM, IUnknown

All COM interfaces must extend IUnknownAll COM interfaces must extend IUnknown

All COM objects must implement IUnknownAll COM objects must implement IUnknown

(36)

Com Interfaces In Nature Com Interfaces In Nature

Represented as pure abstract baseRepresented as pure abstract base classes 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 Basic

Visual Basic

Uniform binary representation independent of how Uniform binary representation independent of how you built the object

you built the object

Identified uniquely by a 128-bit Interface ID (IID)Identified uniquely by a 128-bit Interface ID (IID)

(37)

Com Interfaces In Nature Com Interfaces In Nature

COM interfaces are described first in COM interfaces are described first in COM IDL

COM IDL

COM IDL is an extension to DCE IDL COM 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 code

definitions 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 format easily parsed format

Java Java

/Visual Basic /Visual Basic

®®

pick up mappings from pick up mappings from type library

type library

(38)

Foo.idl Foo.idl

IDLIDL

Description Description of Foo interfaces of Foo interfaces

and datatypes and datatypes

Foo.h Foo.h

C/C++

C/C++

Definitions Definitions

Foo_i.c Foo_i.c

GUIDs GUIDs

Foo_p.c Foo_p.c

Proxy/Stub Proxy/Stub

dlldata.c dlldata.c

Class Loading Class Loading

Support Support

Foo.tlb Foo.tlb

Binary Binary Descriptions Descriptions

MIDL.EXE

MIDL.EXE *.java*.java

Java Java Definitions Definitions

JACTIVEX.EXE JACTIVEX.EXE

COM IDL

COM IDL

(39)

COM IDL COM 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

(40)

[ 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.idl CalcTypes.idl

COM IDL

COM IDL

(41)

COM IDL - C++ Mapping COM 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

(42)

COM IDL – Java/VB Mapping COM 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.java CalcTypes.java

Public Sub Clear( )

Public Sub Add(ByVal n As Integer)

Public Sub GetSum(ByRef pn As Integer)

CalcTypes.cls CalcTypes.cls

(43)

particular value particular value resres

Severity (31)

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

0 -> Success 0 -> Success

1 -> Failure 1 -> Failure

FACILITY_NULL FACILITY_NULL

FACILITY_ITF FACILITY_ITF

FACILITY_STORAGE FACILITY_STORAGE FACILITY_DISPATCH FACILITY_DISPATCH FACILITY_WINDOWS FACILITY_WINDOWS FACILITY_RPC

FACILITY_RPC

COM And Error Handling COM And Error Handling

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

All (remotable) methods must return a standard 32-bit All (remotable) methods must return a standard 32-bit error code called an HRESULT

error code called an HRESULT

– Mapped to exception in higher-level languages

– Overloaded to indicate invocation errors from proxies

(44)

HRESULTs HRESULTs

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 runtime

description at runtime

(45)

small small

longlong hyper hyper

IDLIDL C++C++ JavaJava

short short

charchar

longlong __int64 __int64

bytebyte

intint longlong short

short shortshort

Visual Basic Visual Basic

N/AN/A

LongLong N/AN/A Integer Integer

unsigned small unsigned small

unsigned long unsigned long unsigned hyper unsigned hyper unsigned short unsigned short

unsigned char unsigned char

unsigned long unsigned long unsigned __int64 unsigned __int64

bytebyte

intint longlong unsigned short

unsigned short shortshort

ByteByte

N/AN/A N/AN/A N/AN/A

float float double double

float float double double

float float double double

Single Single Double Double charchar

unsigned char unsigned char

charchar

unsigned char unsigned char

charchar bytebyte

N/AN/A ByteByte wchar_t

wchar_t wchar_twchar_t charchar IntegerInteger

Script Script

NoNo

YesYes NoNo YesYes

NoNo

NoNo NoNo NoNo

YesYes YesYes NoNo YesYes

NoNo

COM Data Types

COM Data Types

(46)

bytebyte

boolean boolean VARIANT_BOOL VARIANT_BOOL

IDLIDL C++C++ JavaJava

BYTEBYTE

unsigned char unsigned char

longlong

VARIANT_BOOL VARIANT_BOOL

charchar

intint boolean boolean unsigned char

unsigned char bytebyte

Visual Basic Visual Basic

N/AN/A

LongLong Boolean Boolean

ByteByte

BSTRBSTR VARIANT VARIANT

BSTRBSTR java.lang.Stringjava.lang.String VARIANT

VARIANT com.ms.com.Variantcom.ms.com.Variant

String String Variant Variant CYCY longlong intint CurrencyCurrency DATEDATE

enumenum

double

double doubledouble enumenum intint

DateDate EnumEnum Typed ObjRef

Typed ObjRef IFoo *IFoo * interface IFoointerface IFoo IFooIFoo struct

struct structstruct final classfinal class TypeType union

union C-style Array C-style Array

union

union N/AN/A

array

array arrayarray

N/AN/A N/AN/A

Script Script

NoNo

NoNo YesYes YesYes

YesYes

YesYes YesYes YesYes

YesYes YesYes NoNo NoNo NoNo

COM Data Types

COM Data Types

(47)

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();

}

Example

Example

(48)

Where Are We?

Where Are We?

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

types called interfaces

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

without concern for C++ compiler incompatibilities

incompatibilities

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

functionality via RTTI-like constructs

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

duplicated or destroyed

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

(49)

Fundamental Architecture Fundamental Architecture

Requirements Requirements

Decoupling Decoupling

– Interfaces

Object creation/destruction Object creation/destruction

– Factory, Reference Counting

Introspection Introspection

– QueryInterface

Language interoperability Language interoperability

– IDL

Dynamic loading Dynamic loading

(50)

References References

Programming Distributed Applications with Programming Distributed Applications with Visual Basic and COM

Visual Basic and COM

– Ted Pattison, Microsoft Press

Inside COM Inside COM

– Dale Rogerson, Microsoft Press

Essential COM(+), 2nd Edition (the book) Essential COM(+), 2nd Edition (the book)

– Don Box, Addison Wesley Longman

DCOM Mailing List DCOM Mailing List

– http://discuss.microsoft.com

Riferimenti

Documenti correlati

Arcs are labeled with the cost of traversing them and the estimated cost to a goal (i.e., the h function) is reported inside nodes (so lower scores are better). Apply

Department of Information Engineering and Computer Science Academic Year 2020/2021...

Department of Information Engineering and Computer Science Academic Year 2020/2021... Algorithms

 The next step is to transform each well-formed formula into Prenex Normal Form, skolemize, and rewrite as clauses in conjunctive normal

So, here we have that garbage is mutex with not clean and with not quiet (the only way to make garbage true is to maintain it, which is mutex with carry and with dolly)...

If you bring in as many team-mates as you like to help David, reallocating some of the tasks to these folk (but nobody is over-allocated work), what is the earliest finish time of

 Represent the following seven sentences using and extending the representations developed in the chapter:.. The water in John’s water bottle

page 015 In terms of the CPTs, you just needed to make sure that adding multiple causes increased the probability of a thing - for instance, if the neighbor’s dog is howling AND