ATL interface mapping macro detailed [8]

zhaozj2021-02-16  75

Nine, com_interface_entry_chain (classname) Part of the ATL routine Commap

Let's take a look at its definition:

#define com_interface_entry_chain (classname) / {null, / (dword) & _ ccomchaindata :: data, / _chain},

Typical usage:

Class Cchain: Public IDispatchiMPL , PUBLIC ISUPPORTERRORINFO, PUBLIC CCOMOBJECTROOT, PUBLIC CCOMCOCLASS {......

It is not different from the general components.

Class Couter: Public cchain, .... {begin_com_map (couter) ... com_interface_entry_chain (cchain) end_com_map ()};

We are very familiar with the process of queries, you can take a look at _Chain's function. _Chain () is a member function of CComobjectRootBase:

Static HRESULT WINAPI _CHAIN ​​(Void * PV, Refiid IID, Void ** PPVObject, DWORD DW) {_TL_Chaindata * PCD = (_TL_Chaindata *) DW; VOID * P = (void *) ((DWORD) PV PCD-> dwoffset) RETURN INTERQUERYINTERFACE (P, PCD-> PFUNC (), IID, PPVObject);} struct _tl_chaindata {dword dwoffset; const _tl_intmap_entry * (WinAPI * PFUNC) ();

Let's take a look at the DW section in the macro:

Template _tl_chaindata _ccomchaindata :: data = {offsetofclass (base, derived), base :: _ geternal

Basically, we have already understood what is going on. Void * p will get the base class pointer, Interalexryinterface we are already very familiar, _chain gives the base class pointer and the base class interface mapping macro to it, actually query The base class interface! ! !

Under normal circumstances, this macro is placed between BeGin_COM_MAP and END_COM_MAP, which means that only the interface of the Father class is only when the interface is not checked in the current class. However, it is often placed in the first place. At this time, I will first check the father-class interface. Only when the parent class does not implement this interface. In ATL components are implemented in multiple inheritance, ATL defines a number of categories to implement some common interfaces, which are often used as the base class of components, so this macro is used in a large number of use.

All of our important macros have been said, the rest is very simple macro. Oh, still put them all, good start.

Ten, com_interface_entry_iid (IID, X)

#define COM_ITERFACE_ENTRY_ID (IID, X) / {& IID, / OffsetOfClass (X, _COMMAPCLASS), / _TL_SIMPLEMAPENTRY}, 11, COM_ITERFACE_ENTRY2_IID (IID, X, X2)

#DEFINE COM_ITERFACE_ENTRY2_IID (IID, X, X2) / {& IID, / (DWORD) ((X *) (_COMMAPCLASS *) 8) - 8, / _tl_simplemapentry},

From the definition, these two macros are just a "IID" compared with COM_ITERFACE_ENTRY () and COM_INTERFACE_ENTRY2 (). There is no other benefit, but it is clearly pointed out by the user to the interface IID, without the system to convert according to the interface name.

12. COM_ITERFACE_ENTRY_FUNC (IID, DW, FUNC)

#define COM_ITERFACE_ENTRY_FUNC (IID, DW, FUNC) / {& IID, / DW, / FUNC},

Remember the code in atlinternalQueryInterface ()? If you find the interface we have to find in the interface mapping table, and this interface is not _ATL_SIMPLEENTRY, the specified function in the macro definition is executed.

This macro gives us a function of writing a handset. This function must be defined below: HRESULT WINAPI FUNC (Void * PV, Refiid Riid, LPVOID * PPV, DWORD DW);

When the AtlinternalQueryInterface calls FUNC, it will pass the relevant information. PV is the pointer of the class object, the RIID is the interface to query, the PPV is the interface pointer to which the query is obtained, DW is the parameters specified in the macro definition. Also if you do not intend to return the interface pointer in the function, PPV should be assigned to null and return S_FALSE or E_NOIInterface. Returns S_FALSE just continues to find it, if you return to E_NOIInterface, the query will be terminated. If the interface pointer is returned, S_OK should be returned.

Thirteen, com_interface_entry_func_blind (dw, func)

#define com_interface_entry_func_blind (DW, FUNC) / {Null, / DW, / FUNC},

As for the characteristics of _blind type, you can see a few sections.

14, com_interface_entry_nointerface (x)

#define COM_INTERFACE_ENTRY_NOINTERFACE (x) / {& _ATL_IIDOF (x), / NULL, / _NoInterface}, _NoInterface is CComObjectRootBase member function to see if it is defined: static HRESULT WINAPI _NoInterface (...) {return E_NOINTERFACE;}

It turns out that it just returns E_NOINTERFACE and terminates the query.

Haha, it seems that I don't want someone to find this interface! ! !

Fifteen, com_interface_entry_break (x)

#define com_interface_entry_break (x) / {& _tl_iidof (x), / null, / _break}, _break is also a member function of CComobjectRootBase, see its definition: static hResult winapi _break (...) {IID; _TLDUMPIID (IID, _T ("Break Due To Qi for Interface", S_OK); debugbreak (); returnous s_false;} If you check this interface, debugbreak () will be called, and return S_FALSE, continue to query. DEBUGBREAK () What is the effect of everyone try it, must be familiar, huh, huh.

At this time, all fifteen interface maps have all been finished, 唉, it is not easy, especially the previous macro tracks. Because of the limitations of text, many things are not easy to express. Some calls are also what I call it myself, may be different from the habits of others. No way, everyone will be just, huh, huh.

转载请注明原文地址:https://www.9cbs.com/read-15313.html

New Post(0)