ATL Learning Notes (4): COM interface mapping table

xiaoxiao2021-03-18  195

In the table driver in CCOMOBJECTROTOBJECTBASE, the inner implementation of the interface is implemented, ienalQueryInterface (). So when you create an ATL-based COM class, you need to create a mapping table that contains all implementations.

1. Begin_COM_MAP, END_COM_MAP, COM_INTERFACE_ENTRY and COM_ITERFACE_ENTRY2 Macro

ATL provides four macows that Begin_COM_MAP, END_COM_MAP, COM_INTERFACE_ENTRY and COM_INTERFACE_ENTRY2 to create an interface mapping table.

Suppose a class CCLASSA inherits the interface IINTA and IINTB, and the interface mapping table of the class is created as follows:

Class CCLASSA: PUBLIC CCOMOBJECTROOTEX {begin_com_map (cclassa) COM_INTERFACE_ENTRY (IINTA) COM_INTERFACE_ENTRY (IINTB) end_com_map () ...};

When CCLASSB inherits IINTC and IINTD, and IINTC and IINTD are inherited from the IdisPatch interface. At this point, if the client program is querying the IDispatch interface, the iDispatch interface pointer returned by QueryInterface will not be able to determine IINTC or IINTD. In this case, you need to specify the default pointing of the IdisPatch interface pointer. COM_INTERFACE_ENTRY2 () macro is used to complete this feature. The following code will default to the IINTD ID interface pointer to the request for the IdisPatch interface.

class CClassB: public CComObjectRootEx {BEGIN_COM_MAP (CClassA) COM_INTERFACE_ENTRY (IIntC) COM_INTERFACE_ENTRY (IIntD) COM_INTERFACE_ENTRY2 (IDispatch, IIntD) END_COM_MAP () ......};

2. Implementation with the interface mapping table

The CClassB Macro expansion in the following code can be obtained with minor streamlining: class CClassB: public CComObjectRootEx {// BEGIN_COM_MAP (CClassB) public: typedef CClassB _ComMapClass; static HRESULT _Cache (void * pv, REFIID iid, void * PPVObject, DWORD_PTR DW) {_commapclass * p = (_commapclass *) PV; P-> Lock (); hresult hres = e_fail; hres = ccomobjectbase :: _ cache (pv, iid, ppvobject, dw); p-> unlock () ; return hRes;} IUnknown * _GetRawUnknown () {return (IUnknown *) ((INT_PTR) this _GetEntries () -> dw);} HRESULT _InternalQueryInterface (REFIID iid, void ** ppvObj) {return InternalQueryInterface (this, _GetEntries ( ), iid, ppvObj);} const static ATL :: _ ATL_INTMAP_ENTRY * _GetEntries () {static const ATL :: _ ATL_INTMAP_ENTRY _entries [] = {// COM_INTERFACE_ENTRY (IIntC) {& _ATL_IIDOF (IIntC), offsetofclass (IIntC, _ComMapClass), _ATL_SIMPLEMAPENTRY }, // COM_ITERFACE_ENTRY (IINTD) {& _ATL_IIDOF (IIntD), offsetofclass (IIntD, _ComMapClass), _ATL_SIMPLEMAPENTRY}, // COM_INTERFACE_ENTRY2 (IDispatch, IIntD) {& _ATL_IIDOF (IIntD), reinterpret_cast (static_cast (static_cast (reinterpret_cast <_ComMapClass * > (8)))) - 8, _TL_SIMPLEMAPENTRY}, // end_com_map () {NULL, 0, 0}}; Return & _Entries;} Virtual Ulong AddRef () = 0; Virtual Ulong Release () = 0; HRESULT QueryInterface REFIID, VOID *) = 0;

According to the above code, the role of Begin_COM_MAP () is the key to provide a static _GetenTries () method for obtaining a static COM interface mapping table created in this method. Where, when the base class (or interface) is the parent class (or interface) of the Derived class (or interface), the OffsetOfClass (BASE, DERIVED) macro is used to return the Base interface (or class) pointer in the class relative to the Derived pointer. The pointer offset value in the derived category. _ATL_SIMPLEMAPENTRY constant represents the second member DW of the _ATL_INTMAP_ENTRY structure represents the offset value of the base to the Derived pointer. COM_ITERFACE_ENTRY2 The main difference between COM_INTERFACE_ENTRY is the calculation of this offset value. At the same time, the END_COM_MAP () macro also declares the iUnknown's addRef () and release () method as a pure virtual function. As a result, the method of the IunkNown interface will be destined to have subclass of such classes.

3. Conclusion

Each ATL-based COM object must first create a static interface mapping table. The creation of this table is done by begin_com_map, end_com_map, com_interface_entry with com_interface_entry2 four macros. They created an interface mapping table and interface mapping table, while also declaring the iUnknown method as a pure virtual function, which will be implemented by its derived class.

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

New Post(0)