First, COM is a better C 1, what Don Box is saying "COM IS Love". The full name of COM is the Component Object Model component object model. 2, from C to DLL to COM2.1 C , such as a software vendor publishing a class library (CMATH four operation), at which time the class library will become an inextensible part of the customer application. Suppose the generated machine code of this library occupies 4MB of space in the target executable. When three applications use the CMATH library, then each executable file contains 4MB library code (see Figure 1.1). When three applications run together, they will take up 12MB virtual memory. The problem is far away. Once the class library vendor finds that the CMATH class library has a defect, release a new class library, which requires all applications that use this class library. There is no other law. Figure 1.1 Three CMATH's three customers 2.2 DLL Solve the above problem is to encapsulate the CMATH class into a dynamic link library (DLL, DYNAMIC LINK LIBRARY). When using this technology, all methods of CMATH will be added to the Export List of the CMATH DLL, and the linker will generate an introduction library. This library exposes the symbol of the CMATH method member. When a customer link is introduced into the library, some settles will be introduced into the executable, which notifies the loader dynamically load CMATH DLL at runtime. When CMATH is in the DLL, his running model is shown in Figure 1.2 CMATH introduction library 2.3 COM "Simply lead C class definition from DLL" This scheme does not provide a reasonable binary component structure. Because the C class is both an interface is also an implementation. Here you need to separate the interface from the implementation to provide binary component structure. At this point, there is a two C class, one as the other as an interface class as an implementation class. Let's start the com tour. Second, COM Basics 1. COM Basic Know 1.1 Return Value HRESULTCOM requires all methods to return a HRESULT type error number. HRESULT is actually a type definition:
Typedef long hresult; See Winerror.h file for the definition of HRESULT
// Values Are 32 Bit Values Layed Out As Follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// ---- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------------------
// | s | res | facility | code |
// ---- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------------------
//
// Where
//
// s - is the severity code
//
// 0 - SUCCESS
// 1 - Error
//
// RES- is a reserved bit
//
// Facility - Is The facility code
//
// Code - Is The Facility ''s Status Code
We generally determine whether the method is successful:
#define succeedededed (hr) (long (hr)> = 0) #define failed (hr) (long (hr) <0)
1.2 first identical IDL
Each standard COM component requires an interface definition file, the file extension is called
IDL. Let us see what the IUNKNOW interface definition file is.
[
Local,
Object,
UUID (000,000-0000-0000-c000-000000000046),
Pointer_DEFAULT (UNIQUE)
]
Interface IUnknown
{
TypedEf [Unique] iUnknown * lpunknown;
CPP_QUOTE ("//")
CPP_QUOTE ("// IID_IUNKNOWN AND All Other System Iids Are Provided in Uuid.lib")
CPP_QUOTE ("// Link That Library In used your proxies, clients and servers)
CPP_QUOTE ("//")
HRESULT QueryInterface
Refiid Riid,
[OUT, IID_IS (RIID)] void ** ppvObject);
Ulong addRef ();
Ulong release ();
}
[local] Attributes prohibits generating network code.
[Object] The property is indicating that the definition is a COM interface instead of the DEC style interface.
[UUID] attribute gives a GUID.
[UNIQUE] Attribute indicates that the NULL (empty) pointer is a legal parameter value.
[Pointer_Defaul] All embedded pointers specify a default pointer property
Typedef [unique] iUnknown * lpunknown; this is a type definition
CPP_QUOTE This is more interesting, this is a method of writing a note in the IDL file. These annotations will be saved to ***. H and *** _ i.c files
[in] said this parameter is income
[OUT] means this parameter is exported
[IID_IS (RIID)] Indicates that this parameter requires the previous RIID parameter. Note: All parameters with OUT properties need to be a pointer type.
1.3 IUNKOWN interface
In addition to IUNKOWN this whole example, others should not feel unfamiliar! COM requirements (the most basic requirements) All interfaces need to be inherited from the iUnknown interface, so the iUnknown interface has the "source of evil".
The IUNKOWN interface defines three ways.
HRESULT QueryInterface ([in] refiid riid, [out] void ** ppv);
Ulong addRef ();
Ulong release (); where
AddReft () and release () are responsible for the object reference count, and the queryinterface () method is used to query the interface implemented. Whenever the COM component is referenced once, an AddRef () method should be called. And when the client needs to call the Release () method when the client is released an interface of the COM component.
Please take care of the example below.
2, a relatively simple COM
This example has four files:
File Name Description Interface.h Interface Class Definition File Math.h and Math.cpp Implementation Class SIMPLE.CPP Main Function File This is used as a client for COM
2.1 interface.h file
#ifndef interface_h
#define interface_h
#include
// {7C8027EA-A4ED-467C-B17E-1B51CE74AF57}
Static const guid iid_isimplemath =
{0x7c8027ea, 0xa4ed, 0x467c, {0xB1, 0x7e, 0x1b, 0x51, 0xce, 0x74, 0xAF, 0x57}}; // {CA3B37EA-E44A-49B8-9729-6E9222CAE84F}
Static const guidiid_iadvancedmath =
{0xCA3B37EA, 0xE44A, 0X49B8, {0x97, 0x29, 0x6e, 0x92, 0x22, 0xca, 0xe8, 0x4f}};
Interface isimath: Public IUNKNOWN
{
PUBLIC:
Virtual Int Add (int NOP1, INT NOP2) = 0;
Virtual int subtract (int NOP1, INT NOP2) = 0;
Virtual Int Multiply (int NOP1, INT NOP2) = 0;
Virtual Int Divide (int NOP1, INT NOP2) = 0;
}
Interface Iadvancedmath: Public IUNKNOWN
{
PUBLIC:
Virtual Int Factorial (int NOP1) = 0;
Virtual Int Fabonacci (INT NOP1) = 0;
}
#ENDIF This file is first #include
The IunkNown Interface Definition File includes coming in.
Next, two interfaces are defined, and the GUID (Globally Unique Identifier Global Unique Identifier) It guarantees the only time and space.
Four methods are defined in the ISMIPLEMATH interface, and two methods are defined in the IadvancedMath interface. These methods are virtual functions, and the entire IsMipleMath and IadvancedMath abstraction are used as binary interfaces.
2.2 Math.h file
#include "interface.h"
Class Cmath: Public Isimplemath,
Public Iadvancedmath
{
Private:
Ulong m_cref;
Private:
INT CALCFACTORIAL (int NOP);
INT CALCFABONACCI (INT NOP);
PUBLIC:
// iUnknown method
STDMETHOD (QueryInterface) (Refiid Riid, Void ** PPV);
STDMETHOD_ (ULONG, ADDREF) ();
STDMETHOD_ (ULONG, RELEASE) ();
// Isimplemath Method
INT Add (int NOP1, INT NOP2);
Int subtract (int NOP1, INT NOP2);
INT MULTIPLY (int NOP1, INT NOP2);
Int Divide (int NOP1, INT NOP2);
// Iadvancedmath Method
INT FACTORIAL (INT NOP);
INT Fabonacci (int NOP);
}; This type is implemented, he implements two interface classes for IsMiplemath and Iadvancedmath (of course, only one interface class can only be implemented).
Note: m_cref is used for object counts. When m_cref is 0 component objects, it should be automatically deleted.
2.3 Math.cpp file
#include "interface.h"
#include "math.h"
STDMETHODIMP CMATH :: QueryInterface (Refiid Riid, Void ** PPV) {// Here is the function of implementing Dynamic_cast, but because Dynamic_CAST is related to the compiler.
IF (riid == iid_isimplemath)
* ppv = static_cast
(this);
Else IF (riid == iid_iadvancedmath)
* ppv = static_cast
(this);
Else IF (riid == iid_iunknown)
* ppv = static_cast
(this);
Else {
* ppv = 0;
Return E_NOINTERFACE;
}
Reinterpret_cast
(* ppv) -> addRef (); // This is this because the reference count is for components.
Return S_OK;
}
STDMETHODIMP_ (ULONG) CMATH :: AddRef ()
{
Return m_cref;
}
STDMETHODIMP_ (ULONG) CMATH :: release ()
{
Ulong res = --m_cref; // Use temporary variables to cache the modified reference count value
If (res == 0) // Because the data will be quoted after the object has been destroyed, this object will be illegal.
DELETE THIS;
Return res;
}
INT CMATH :: Add (int NOP1, INT NOP2)
{
RETURN NOP1 NOP2;
}
INT CMATH :: Subtract (int NOP1, INT NOP2)
{
RETURN NOP1 - NOP2;
}
INT CMATH :: Multiply (int NOP1, INT NOP2)
{
Return NOP1 * NOP2;
}
INT CMATH :: Divide (int NOP1, INT NOP2)
{
RETURN NOP1 / NOP2;
}
INT CMATH :: CalcFactorial (int NOP)
{
IF (NOP <= 1)
Return 1;
Return NOP * CALCFACTORIAL (NOP - 1);
}
Int cmath :: Factorial (int NOP)
{
Return CalcFactorial (NOP);
}
Int cmath :: Calcfabonacci (int NOP)
{
IF (NOP <= 1)
Return 1;
RETURN CALCFABONACCI (NOP - 1) Calcfabonacci (NOP - 2);
}
Int cmath :: Fabonacci (int NOP)
{
Return Calcfabonacci (NOP);
}
Cmath :: cmath ()
{
m_cref = 0;
}
This file is a CMATH class definition file.
2.4 Simple.cpp file
#include "math.h"
#include
Using namespace std;
Int main (int Argc, char * argv [])
{
ISIMPLEMATH * PSIMPLEMATH = NULL; // Declaration Interface Pointer
Iadvancedmath * padvmath = NULL;
// Create an object instance, we temporarily create an object instance, COM has a mechanism for creating an object instance
CMATH * PMATH = New CMATH;
// Query the interface ISIMPLEMATH PMATH-> Queryinterface (IID_ID_IMPLEMATH, (Void **) & psimplemath; if (psimplemath) cout << "10 4 =" << psimplemath-> add (10, 4) << ENDL ; // Query the interface Iadvancedmath psimth-> queryinterface (IID_IADVANCEDMATH, (void **) & padvmath; if (padvmath) cout << "10 fabonacci is" << "10) << 10) << endl; padvmath -> Release (); psimplemath-> release (); return 0;}
This file is equivalent to the client's code, first create a CMATH object, then query the required interface according to this object, if the required interface pointer is correct, then call the interface method, and finally release the interface.
2.5 binary structural diagram of Math components
Figure 1.3 Math component binary structure diagram
2.6 small knot
This example is not a true COM component (he is not a dll) in strict sense (he is not a dll), but he has complied with the minimum requirement of COM (implementing the iUnknown interface). Let's take a COM DLL (but not ATL).
(to be continued)