Detailed description of ATL interface ing macros [5]

Source: Internet
Author: User
5. com_interface_entry_aggregate (IID, punk) parameter ATL routine commap

This section describes the macros used to aggregate objects in ATL. For more information about the concept of a clustered object, see other reference books.
Now let's take a look at the typical usage of this macro:
Class cnames:
Public idispatchimpl,
Public isupporterrorinfo,
Public ccomobjectroot,
Public ccomcoclass
{
.....
};
Caggregate is a clustering class. Its implementation is no different from that of General ATL components, but note that in its class definition
Add declare_no_aggregatable.
Class couter:
Public cchainbase,
Public idispatchimpl,
Public ccomcoclass
{
Hresult finalconstruct ();
Void finalrelease ();
Begin_com_map (couter)
Com_interface_entry_aggregate (iid_igate, m_punkagg.p)
End_com_map ()
Declare_get_controlling_unknown ()
Ccomptr m_punk.pdf;
};

Couter includes the aggregation component cuter, which has the following differences:
(1) added the com_interface_entry_aggregate (iid_igate, m_punkagg.p) Macro.
# Define com_interface_entry_aggregate (IID, punk )/
{& IID ,/
(DWORD) offsetof (_ commapclass, punk ),/
_ Delegate },
Offsetof we have seen it in the previous section. We can guess that it calculates the position of punk in the class. That's it.
Is the position of m_punkagg in the couter.
(2) added the macro declare_get_controlling_unknown (), which is defined:
# Define declare_get_controlling_unknown () Public :/
Virtual iunknown * getcontrollingunknown () {return getunknown ();}
We also need to go further, and we can see from the literal meaning that this function will return the iunknown of the component.
Pointer.
(3) Add a member variable ccomptr m_punkagg to the couter;
M_punkunknown is used to obtain the iunknown pointer of the clustered component.
(4) The finalconstruct and finalrelease are reloaded.
Hresult couter: finalconstruct ()
{
Iunknown * punkouter = getcontrollingunknown ();
Hresult hres = cocreateinstance (clsid_cuter, punkouter,
Clsctx_inproc_server, iid_iunknown, (void **) & m_punkwn );
If (hres! = S_ OK)
Return hres;
Return s_ OK;
}
Void couter: finalrelease ()
{
M_punkagg.release ();
.....
}
After the couter component is created, finalconstruct will be called, so a clustered component will be created here. In principle
A clustering component can be created only when necessary, but it can also be created along with the components that contain it. Aggregation component
The iunknown pointer is queried and returned to m_punkdetail. External
The aggregate component is operated through m_punkvolumes. In addition, it is noted that punkouter is used as the cocreateinstance
This will create a ccomaggobject object, which contains a ccomcontainedobject
Contains objects. Similar to ccomcachedtearoff in the previous section, ccomaggobject is not
Derived from couter, so the real component object is not a ccomaggobject object, but its internal package
Ccomcontainedobject object. Similarly, punkouter will obtain the ccomaggobject <>
The iunknown pointer will call the ccomcontainedobject's
_ Internalqueryinterface function (well, I guess it all now. Check if I guess it is correct)

Run pouter-> QueryInterface (iid_iagg, (void **) & pagg1)
Function stack 1:
9. ATL: atlinternalqueryinterface (...)
8. ATL: ccomobjectrootbase: internalqueryinterface (...)
7. cnames: _ internalqueryinterface (...)
6. ATL: ccomaggobject: QueryInterface (...)
5. ATL: ccomobjectrootbase: _ delegate (...)
4. ATL: atlinternalqueryinterface (...)
3. ATL: ccomobjectrootbase: internalqueryinterface (...)
2. couter: _ internalqueryinterface (...)
1. ATL: ccomobject: QueryInterface (...)

Explanation:
1-5: we have seen the call of these functions many times, because _ delegate is used in this macro definition, so
Ccomobjectrootbase: _ delegate (...).
Static hresult _ delegate (void * PV, refiid IID, void ** ppvobject, dword dw)
{
Hresult hres = e_nointerface;
Iunknown * P = * (iunknown **) (DWORD) PV + DW );
If (P! = NULL)
Hres = p-> QueryInterface (IID, ppvobject );
Return hres;
}
The meaning of the second sentence has been seen in the previous section. The final result is P = couter: m_punkagg.
6: as we expected, ccomaggobject: QueryInterface () is called ()
Stdmethod (QueryInterface) (refiid IID, void ** ppvobject)
{
// If iunknown is queried, then ....
Else
Hres = m_contained. _ internalqueryinterface (IID, ppvobject );
Return hres;
}
As we expected, it will be handed over to its containing objects for implementation. (This code has been seen in the previous section, right)
7-9: same as in the previous section, it will be handed over to csf-::_ internalqueryinterface (...), and the rest of the work will be done by csf-
Finished. The returned pointer is actually the interface pointer of the ccomcontainedobject component.

Run pagg1-> QueryInterface (iid_iagg, (void **) & pagg2)
Function stack 2:
9. cnames: _ internalqueryinterface (...)
8. ATL: ccomaggobject: QueryInterface (...)
7. ATL: ccomobjectrootbase: _ delegate (...)
6. ATL: atlinternalqueryinterface (...)
5. ATL: ccomobjectrootbase: internalqueryinterface (...)
4. couter: _ internalqueryinterface (...)
3. ATL: ccomobject: QueryInterface (...)
2. ATL: ccomobjectrootbase: outerqueryinterface (...)
1. ATL: ccomcontainedobject: QueryInterface (...)

Explanation:
1-9: browsing the entire stack is too close to the stack 2 we saw in the previous section, because the inclusion
Image. The contained object acts as a proxy. He first submits the query to the external object (couter) for (step 1 and 2 ),
When an external object finds that the interface of the aggregation component is to be queried, it will return the query to it for retention.
Pointer of the clustering component (m_punkcomponent, in step 2, note that this is not a real clustering component ).
Submit the query to the contained object (in step 1), and then submit the query to the class csung (step 2) that actually implements the interface ).
If the external object finds that the interface of the external component is to be queried, it is easy to directly query the interface. This
This prevents the inconsistency between the query operations of external components and aggregation components.
Alas, the process is really troublesome, but it's okay. It's similar to the macro in the previous section. For relevant source code, see the previous section.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.