Originally, through the Cast converter of the C compiler has the calculation capabilities of the address offset, you can complete the task.
But ATL is also used in the style of construction (Data Drive, Data-Driven) to get better performance and
Flexibility, in fact, (in fact, it is very different, it is very small, essentially in the CAST scheme,
Every time you start from this, the offset is calculated to get the correct interface entry point. And the data driver can be directly
Direct query gets the interface entry point because it calculates the offset when compiling, exists in the table.)
Third, macroblock
MFC
Part1 ---- The origin of the interface foundation structure
Naturally, the class nested scheme adopted by MFC must have special constructions to support COM consciousness.
Talking about MFC support for COM, you must know CCMDTARGET, which provides a lot of automation
Support, (Note: I feel that MFC supports COM, the eyes do not leave Automation, mainly
Reflecting the interface of the default declaration for Dispinterface, which makes it always use in an unknown service
The distribution of the interface, even if it is a C environment).
(Reaicable: This article only for INPRO components, to analyze the framework, in fact, other types of only based on it
Of course, the COM system is huge.)
Establish component class:
In your .dll file, your component class needs to be derived from ccmdtarget.
Because it provides a large number of support for COM development.
Establish an interface and implement an interface mapping table:
-------------------------------------------------- -------------------------------------------------- -------------------------------------
DECLARE_INTERFACE_MAP () Macro
-------------------------------------------------- -------------------------------------
#ifdef _AFXDLL
#define declare_interface_map () /
PRIVATE: /
Static const AFX_INTERFACEMAP_ENTRY _INTERFAENTRIES []; /
/ / Define the interface mapping table of the component class
protected: /
Static const AFX_INTERFACEMAP InterfaceMap; /
/ / Define the AFX_InterfaceMap variable,
/ / For the current class, when the interface is not found,
/ / Back to the base class to find
// The entry point of the current interface mapping table is also stored.
Static const AFX_INTERFACEMAP * PASCAL _GETBASEINTERFACEMAP (); /
/ / INTERFACEMAP for the base class
Virtual const AFX_INTERFACEMAP * GetInterfaceMap () const; /
// Get interfacemap of the component class
#ELSE
#define declare_interface_map () /
PRIVATE: /
Static const AFX_INTERFACEMAP_ENTRY _INTERFAENTRIES []; /
protected: /
Static const AFX_INTERFACEMAP InterfaceMap; /
Virtual const AFX_INTERFACEMAP * GetInterfaceMap () const; /
#ENDIF
-------------------------------------------------- -------------------------------------------------- ------------------------------ Begin_Interface_map (csam, ccmdtarget) [. CPP]
// csam is the component class name interface_part (CSAM, IID_ICOM, DISPATCH)
END_INTERFACE_MAP ()
Macroscope
-------------------------------------------------- -----------------------------------
#ifdef _AFXDLL
#define begin_interface_map (theclass, thebase) /
Const Afx_Interfacemap * Pascal Theclass :: _ getBaseInterfaceMap () /
{RETURN & Thebase :: InterfaceMap;} /
/ / Define static member functions for the INTERFACEMAP first site of the base class
Const Afx_InterfaceMap * Theclass :: getInterfaceMap () Const /
{RETURN & THECLASS :: InterfaceMap;} /
// Define the static member function of the acquisition component class interface mapping table
AFX_COMDAT const AFX_DATADEF AFX_INTERFACEMAP THECLASS :: InterfaceMap = /
{& Theclass :: _ GetBaseInterfaceMap, & Theclass :: _ interfaceEntries [0],}; /
// Fill: GetThisInterfaceMap function pointer and
// The interface mapping table entry point of this component
AFX_COMDAT Const AFX_DATADEF AFX_INTERFACEMAP_ENTRY THECLASS :: _ interfaceentries [] = /
{/
#ELSE
#define begin_interface_map (theclass, thebase) /
Const Afx_InterfaceMap * Theclass :: getInterfaceMap () Const /
{RETURN & THECLASS :: InterfaceMap;} /
AFX_COMDAT const AFX_DATADEF AFX_INTERFACEMAP THECLASS :: InterfaceMap = /
{& Thebase :: InterfaceMap, & Theclass :: _ InterfaceEntries [0],}; /
AFX_COMDAT Const AFX_DATADEF AFX_INTERFACEMAP_ENTRY THECLASS :: _ interfaceentries [] = /
{/
#ENDIF
#define interface_part (THECLASS, IID, LOCALCLASS) /
{& IID, Offsetof (THECLASS, M_X ## localclass)}, /
// Fill the interface shot table
#define interface_aggregate (THECLASS, THEAGGR) /
{Null, Offsetof (THECLASS, THEAGGR)}, /
// It is worth talking about whether the MFC supports COM's method of components.
//
#define end_interface_map () /
{NULL, (SIZE_T) -1} /
}; /
/ / Sign Interface Map Table End
#ndif //! _AFX_NO_OLE_SUPPORT
-------------------------------------------------- -------------------------------------------------- ------------------------------------------
The above two sets of macros are inseparable from the AFX_INTERFACE_ENTRY structure and the AFX_Interface structure. Let's take a look at these two structures:
STRUCT AFX_INTERFACEMAP_ENTRY / / Interface Map Table Structure
{
Const void * piid; // interface flag (NULL for aggregate)
SIZE_T Noffset; // Offset of the interface vTable from M_Unknown
// Interface (nested) and the offset of the package
}
Struct AFX_INTERFACEMAP
{
#ifdef _AFXDLL
Const AFX_INTERFACEMAP * (PASCAL * PFNGETBASEMAP) (); // Null Is Root Class
// Define function pointer
#ELSE
Const AFX_INTERFACEMAP * PBASEMAP;
//
#ENDIF
const AFX_ITERFACEMAP_ENTRY * PENTRY; // map for this class
// Interface mapping table entry point pointer
}
What is the two groups above?
They have made the following few things in the interior of the component class: (analysis of Define _AFXDLL)
1. Establish an interface mapping table.
The structure of the table is AFX_INTERFACEMAP_ENTRY
This structure records PIID, interface markers and
Interface and wrapping offset
The actual action is as follows:
#define interface_part (THECLASS, IID, LOCALCLASS) /
{& IID, Offsetof (THECLASS, M_X ## localclass)}, /