Explore the MFC and ATL of the COM Development Frame [Three]

zhaozj2021-02-16  51

1. In fact, the component class get the interface mapping table is the first GetInterfaceMap () static member function

Get an InterfaceMap structure variable, the second value of this variable is the entry of the interface mapping table.

The first value of InterfaceMap saves the _getBaseInterfaceMap function pointer of the base class.

When the interface is not found in the component class, pass _getBaseInterfaceMap

Get the foundation of InterfaceMap, thereby obtaining the interface mapping table inlet of the base class ....

This is continuously traced..

Through these macros, we implemented interface mapping tables and provided in the class level.

Method. This way, component classes can be locate the query and address of the interface through this table.

However, there is still a big problem here.

We said that any interface must implement AddRef, Release, QueryInterface.

(Note 2: In fact, the definition of the interface has changed after Idispatch appears, you can put any

The combination of methods and data is achieved as an interface.) ... You haven't seen anything about this here ..

Yes, there is still a "big conspiracy" .... About this

#define interface_part (THECLASS, IID, LOCALCLASS) /

{& IID, Offsetof (THECLASS, M_X ## localclass)}, /

// Fill the interface shot table

Stand out ....

In actual engineering, the default above LocalClass will be replaced by Dispatch.

What is DISPATCH? In fact, in CDK1.0, COM development does not have to be above these macros.

Where you can clearly see the essence of the problem, no way, the time has changed, and the situation in front of

Discuss it ...

The location of the Dispatch is specified in the nested class of the interface ...

Then there is no doubt that dispatch is nested. But you said, where is this?

In fact, in the ccmdtarget, there is such a piece:

Struct xdispatch

{

DWORD M_VTBL; // Place-Holder for iDispatch VTABLE

#ifndef _AFX_NO_NESTED_DERIVATION

SIZE_T M_NOFFSET;

#ENDIF

} m_xdispatch;

It will become a nested class that implements the interface.

How can this be a nested class? It does n'thing ... Simply structured ...

Internally, there is the same virtual table vTable assignment behavior, which is this behavior makes m_xdispatch thoroughly

Changed, this behavior of this behavior is EnableAutomation () in the component class constructor.

code show as below:

Void ccmdtarget :: enableautomation ()

{

Assert (GetDispatchMap ()! = Null); // Must Have Declare_Dispatch_map

// Construct an COLEDISPATCHIMPL Instance Just To Get To The VTable

ColedispatchImpl dispatch;

// vTable Pointer SHOULD BE Already Set To Same or Null

Assert (m_xdispatch.m_vtbl == null ||

* (DWORD *) & dispatch == m_xdispatch.m_vtbl);

// sizeof (ColedispatchImpl) Should Be Just A DWORD (VTable Pointer)

Assert (sizeof (m_xdispatch) == sizeof (COLEDISPATCHIMPL));

// copy the vtable (AND Other data) to make sure it is initialized

m_xdispatch.m_vtbl = * (dword *) & dispatch;

* (COLEDISPATCHIMPL *) & m_xdispatch = dispatch;}

Part 2 deep into ccmdtarget to see the implementation of the three elements of COM

The reason why us go deep into ccmdtarget

I don't think it is just to implement it.

We want to know a great scene of MFC to COM: polymerization

How is it implemented?

Don't say two words, put out the frame:

PUBLIC:

// data used when ccmdtarget is Made Ole Aware

Long m_dwref;

LPUNKNOWN M_POUTERUNKNOWN; // External Controlling Unknown if! = NULL

DWORD M_XINNERUNKNOWN; // Place-Holder for Inner Controlling Unknown

PUBLIC:

// Advanced Operations

Void enableaggregation (); // call to enable aggregation

Void externaldisconnect (); // forcibly disconnect

LPunknown getControllingunkNown ();

// Get Controlling iUnknown for aggregate cree

// THESE VERSIONS DO NOT DELEGATE TO M_POUTERUNKNOWN

DWORD INTERQUERYINTERFACE (const void *, lpvoid * ppvobj);

DWORD INTERNALADDREF ();

DWORD INTERNALESE ();

// THESE VERSIONS DELEGATE TO M_POUTERUNKNOWN

DWORD EXTERNALQUERYINTERFACE (const void *, lpvoid * ppvobj);

DWORD EXTERNALADDREF ();

DWORD EXTERNALRELEASE ();

//Mplementation Helpers

LPunknown GetInterface; Const Void *);

LPunkNown QueryAggregates (const void *);

// Advanced Overrideables for Implementation

Virtual bool oncreateaggregates ();

Virtual lpunknown getInterfaceHook (const void *);

From the above statement, you can find:

Here, two standard interface methods are declared.

ExternalXX corresponds to the entrustment IUnknown in the COM model

And INTERNALXX corresponds to non-entrusting IUNKNOWN

With these two interface methods, the achievement of aggregation is OK ....

For details on aggregation, for details, please refer to relevant special

Books, no more details here.

The foundation structure of the interface is completed by Part1 and Part 2.

Part3 -------- Class factory

Needless to say, COM objects are created in need of class.

-------------------------------------------------- -------------------------------------------------- -----

Declare_olecreate (csam) macroblock

-------------------------------------------------- ---------------------------

#define declare_olecreate (Class_name) /

PUBLIC: /

Static AFX_Data ColeObjectFactory Factory; /

// Define the class factory object ...

Static Afx_Data Const Guid Guid; /

// Component Class GUID

-------------------------------------------------- -------------------------------------------------- ------------

Implement_olecreate macroblock

-------------------------------------------------- ----------------

#define import_olecreate (Class_name, External_Name, L, W1, W2, B1, /

B2, B3, B4, B5, B6, B7, B8) /

AFX_DATADEF COLEOBJECTFAACTORY CLASS_NAME :: Factory (class_name :: Guid, /

Runtime_class (class_name), false, _t (external_name)); /

/ / What to pay attention to is external_name: progid

AFX_COMDAT const AFX_DATADEF GUID CLASS_NAME :: Guid = /

{L, W1, W2, {B1, B2, B3, B4, B5, B6, B7, B8}}; /

// Give the CLSID of the component class to the member variable GUID of the component class.

-------------------------------------------------- -------------------------------------------------- -------

Implement_olecreate (CSAM, "MFCcom.sam",

0x43d242f9, 0x4f7e, 0x4cbb, 0xae, 0xDa, 0x77, 0x8d, 0xa1, 0x16, 0xD0, 0xD9)

Description: We know that when you create a component class object, you first get the current state by the app core.

Remove the class factory table from the middle, get the corresponding class factory object pointer according to CLSID. It is here

Associate information such as class and CLSID, ProID.

PART4 ------- Automation

In fact, automation is also a great subject. Automation technology enhances the environmental adaptability of components.

For automation components in the MFC, because the default interface is DISPINTERFACE, it is

Accessions use distribution means. Unlike your consciousness, always keep in mind through vtable [_index]

To access the method. In the process of using the component, first get the idispatch interface, then call IDispatch

Method GetidsOfNames gets the token (ID) of the method of Programmers hopes, finally passed

Idispatch's method invoke is executed. This technology allows scripts and macro environments to use COM

Objects, but for environments with pre-compilation, it will make the performance of the component system

Discount. Because it is more than one intermediate layer repeatedly called.

About Dispatch support, basically constructing the principle of thinking with

The above INTERFACE.

-------------------------------------------------- -------------------------------------------------- -------------------

Declare_dispatch_map ()

Begin_Dispatch_map (csam, ccmdtarget) [. CPP]

DISP_PROPERTY_NOTIFY (CSAM, "Fook", M_fook, OnfookChanged, VT_R4)

DISP_FUNCTION (CSAM, "Post", POST, VT_R4, VTS_NONE)

END_DISPATCH_MAP ()

Mobility ------------------------------------------------ -------------------- # IFDEF_AFXDLL

#define declare_dispatch_map () /

PRIVATE: /

Static const AFX_DISPMAP_ENTRY _DISPATCHENTRIES []; /

Static uint _dispatchentrycount; /

Static DWORD _DWSTOCKPROPMASK; /

protected: /

Static AFX_DATA const AFX_DISPMAP DispatchMap; /

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

New Post(0)