09 COM Fundamentals1
09 COM Fundamentals1
Of COM(+)
(Part 1)
Don Box
Cofounder
DevelopMentor
http://www.develop.com/dbox
11-203
Motivation
A Solution Components
Recall: Class-Based oo
Recall: Class-Based oo
// 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 Pitfalls
// faststring.h
class __declspec(dllexport) FastString {
char *m_psz;
public:
FastString(const char *psz);
~FastString();
int Length() const;
int Find(const char *pszSearchString) const;
};
Client A
Client B
faststring.dll
Client C
faststring.lib
import name
file name
export name
??@3fFastString_6Length
??@3fFastString_4Find
??@3fFastString_ctor@sz2
??@3fFastString_dtor
faststring.dll
faststring.dll
faststring.dll
faststring.dll
??@3fFastString_6Length
??@3fFastString_4Find
??@3fFastString_ctor@sz2
??@3fFastString_dtor
// faststring.h
int FastString::Length() const {
class FastString {
return strlen(m_psz);
char *m_psz;
}
public:
FastString(const char *psz);
~FastString();
int Length() const;
int Find(const char *pszSearchString) const;
};
sizeof==8
Client A
sizeof==4
Client B
sizeof==4
Client C
sizeof==8
faststring.dll
faststring.dll
(v1)
FastString::FastString
FastString::~FastString
FastString::Length
FastString::Find
Conclusions
Interface-Based
Programming
Abstract Bases As
Interfaces
Interfaces And
Implementations
Exporting Using
Abstract Bases
Client
pfs
Object
vptr
FastString::Delete
m_text
FastString::Length
m_length
FastString::Find
Interfaces And
Plug-compatibility
Example: Adding
Extended Functionality
// 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 Functionality
Client
Object
pfs
pfnf
FastString::Delete
vptr
FastString::Length
m_text
FastString::Find
m_length
FastString::FindN
Example: Adding
Orthogonal Functionality
Example: Adding
Orthogonal Functionality
Client
Object
pfs
ppo
FastString::Delete
vptr
FastString::Length
vptr
FastString::Find
m_text
m_length
FastString::Delete
FastString::Load
FastString::Save
Fixing Interface-Based
Programming In C++
UUIDs from OSF DCE are compact (128 bit), efficient and
guarantee uniqueness
UUIDs are basically big, unique integers!
QueryInterface
QueryInterface As A Better
Dynamic Cast
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
:
:
:
Fixing Interface-Based
Programming In C++
Fixing Interface-Based
Programming In C++
pCalc4->Release();
pPhone1->Release();
pPhone2->Release();
IUnknown
COM IDL
Foo.h
C/C++
Definitions
Foo_i.c
GUIDs
Foo.idl
IDL
Description
of Foo interfaces
and datatypes
Foo_p.c
MIDL.EXE
Proxy/Stub
dlldata.c
Class Loading
Support
Foo.tlb
Binary
Descriptions
*.java
Java
Definitions
JACTIVEX.EXE
COM IDL
COM IDL
CalcTypes.idl
[ 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
}
__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;
CalcTypes_i.c
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 } };
/**@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.cls
Public Sub Clear( )
Public Sub Add(ByVal n As Integer)
Public Sub GetSum(ByRef pn As Integer)
Severity (31)
res
0 -> Success
1 -> Failure
Facility (27-16)
Code (15-0)
particular value
FACILITY_NULL
FACILITY_ITF
FACILITY_STORAGE
FACILITY_DISPATCH
FACILITY_WINDOWS
FACILITY_RPC
HRESULTs
<FACILITY>_<SEVERITY>_<CODE>
DISP_E_EXCEPTION
STG_S_CONVERTED
<SEVERITY>_<CODE>
S_OK
S_FALSE
E_FAIL
E_NOTIMPL
E_OUTOFMEMORY
E_INVALIDARG
E_UNEXPECTED
C++
Java
Visual Basic
Script
small
char
byte
N/A
No
short
short
short
Integer
Yes
long
long
int
Long
Yes
hyper
__int64
long
N/A
No
unsigned small
unsigned char
byte
Byte
No
unsigned short
unsigned short
short
N/A
No
unsigned long
unsigned long
int
N/A
No
unsigned hyper
unsigned __int64
long
N/A
No
float
float
float
Single
Yes
double
double
double
Double
Yes
char
char
char
N/A
No
unsigned char
unsigned char
byte
Byte
Yes
wchar_t
wchar_t
char
Integer
No
C++
Java
Visual Basic
Script
byte
unsigned char
char
N/A
No
BYTE
unsigned char
byte
Byte
Yes
boolean
long
int
Long
No
VARIANT_BOOL
VARIANT_BOOL
boolean
Boolean
Yes
BSTR
BSTR
java.lang.String
String
Yes
VARIANT
VARIANT
com.ms.com.Variant
Variant
Yes
CY
long
int
Currency
Yes
DATE
double
double
Date
Yes
enum
enum
int
Enum
Yes
Typed ObjRef
IFoo *
interface IFoo
IFoo
Yes
struct
struct
final class
Type
No
union
union
N/A
N/A
No
C-style Array
array
array
N/A
No
Example
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);
}
References
Inside COM
http://www.develop.com
http://discuss.microsoft.com