Saturday, 9 March 2013

The Component Object Model


The Component Object Model

The heart of ActiveX is the Component Object Model (COM). This is an incredibly
complex topic that deserves a book of its own. Luckily, the Microsoft Foundation
Classes and the Visual C++ AppWizard do much of the behind-the-scenes work for you.
The discussion in these chapters is just what you need to know to use COM as a
developer.
COM is a binary standard for Windows objects. That means that the executable code (in
a DLL or EXE) that describes an object can be executed by other objects. Even if two
objects were written in different languages, they are able to interact using the COM
standard.
NOTE: Because the code in a DLL executes in the same process as the
calling code, it's the fastest way for applications to communicate. When
two separate applications communicate through COM, function calls from
one application to another must be marshaled: COM gathers up all the
parameters and invokes the function itself. A standalone server (EXE) is
therefore slower than an in-process server (DLL).
How do they interact? Through an interface. An ActiveX interface is a collection of
functions, or really just function names. It's a C++ class with no data, only pure virtual
functions. Your objects inherit from this class and provide code for the functions.
(Remember, as discussed in Appendix A, "C++ Review and Object-Oriented Concepts," a
class that inherits a pure virtual function does not inherit code for that function.)
Other programs get to your code by calling these functions. All ActiveX objects must
have an interface named IUnknown (and most have many more, all with names that
start with I, the prefix for interfaces).
The IUnknown interface has only one purpose: finding other interfaces. It has a
function called QueryInterface() that takes an interface ID and returns a pointer to
that interface for this object. All the other interfaces inherit from IUnknown, so they
have a QueryInterface() too, and you have to write the code - or you would if there was
no MFC. MFC implements a number of macros that simplify the job of writing interfaces
and their functions, as you will shortly see. The full declaration of IUnknown is in

Listing 13.1. The macros take care of some of the work of declaring an interface and
won't be discussed here. There are three functions declared: QueryInterface(), AddRef(),
and Release(). These latter two functions are used to keep track of which applications
are using an interface. All three functions are inherited by all interfaces and must be
implemented by the developer of the interface.
Listing 13.1 IUnknown, Defined in \Program Files\Microsoft Visual
Studio\VC98\Include\unknwn.h
MIDL_INTERFACE("00000000-0000-0000-C000-000000000046")
IUnknown
{
public:
BEGIN_INTERFACE
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
= 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
#if (_MSC_VER >= 1200) // VC6 or greater
template <class Q>
HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
{
return QueryInterface(__uuidof(Q), (void**)pp);
}
#endif
END_INTERFACE
};

No comments:

Post a Comment