FMD Studio VC Programming Technical Articles:
[
Back to previous points]
Numbering
Subject
Originate
Recording time
4
MFC support analysis of COM interface
Self-writer
00.05.08
MFC support analysis of COM
The MFC uses a C nesting method to implement the COM interface.
In order to simplify the writing. A large number of macro definitions are used.
The following will begin from the original write method of nested classes, and the support of COM is analyzed in the MFC.
First, COM overview
1.com provides a simple binary object usage method. In order to comply with the COM specification. The object (class) code written in VC must be compiled, "interface" can be provided in accordance with the format of the COM specification.
2. About the interface, the interface is a pointer, pointer points to a table, the form contains a pointer to a set of functions that can operate objects.
3.C class definition structure supports the interface.
In order to support polymorphism, the C object containing the virtual function will contain a pointer to the virtual function table, which conforms to the COM interface specification.
There are multiple interfaces that operate the same object. In the C class definition, multiple interfaces can be implemented in two options.
One is a multi-inheritance structure, and a class is derived from multiple interface classes.
The other is a nested class definition structure.
ATL uses the former, MFC adopts the latter.
4. In addition to the normative call method, COM also standardizes the establishment of the object, the survival period, etc.
Each COM object corresponds to a "class" object, and the class factory object contains createInstance (..) member, responsible for the establishment of the object, after the establishment, the interface is available.
In the component (DLL) containing the COM object, there should be a DLLGETCLASSOBJECT exit function, which is used for the system's COM library, in DllgetClassObject, the class is established, the class factory interface returns to the system COM library.
According to the class factory interface, call CreateInstance to establish a COM object and return to the user. The user uses the interface call interface member operation object.
5. Summary
To provide a COM object in the DLL project, you need to define the properties and behaviors of the object with the form of the C class, but this class is invisible to the user, the user operates through the interface operation, so, in the construction of the class, you need to provide appropriate The interface is provided to the user.
In order to match the system's COM library, the DLL should provide several output functions. And provide a class factory for the specified object, and the establishment of objects in the class factory.
Second, provide a class interface with a structure of C nest.
If a class definition contains a set of virtual functions, its object is in the memory structure in the memory.
Therefore, in the encapsulation class of the entire object, nesting defines a few classes that contain specific virtual functions, as well as nested members.
The structure of nested classes is set to provide the structure of the interface. (Delivered from I ...)
example:
1. Define parts:
1 definition of interface structure (virtual function combination)
Class ispellcheck: public icnknown // interface one
{
PUBLIC:
Virtual Bool __stdcall checkword (string, string *) = 0;
}
Class iDictionary: public icnknown // interface two
{
PUBLIC:
Virtual bool __stdcall initialize () = 0;
...
}
2 In class definition, nested definitions The above interface class is derived and members.
Class CDICTIONARY
{
... QueryInterface (...); file: // iunknown needs to be used.
... addRef ();
... release ();
...
Class XDICTIONARYOBJ: PUBLIC IDICTIONARY / / Interface Definition
{
Virtual ulong _stdcall addref ();
...
} m_dictionaryObj; // Interface member (its memory structure contains a virtual function table pointer, which is required for the interface structure.
...
Class XspellCheckobj: Public IsllCheck
{
Virtual ...
...
} m_spellcheckobj; // Interface member
...
}
In nested classes, the original class is required, so that members in each of the nested classes save the original class pointer.
3 Need to define a class factory object class with the top category.
2. Implement
1 implementation of each member
2 Writing a suitable iUnknown implementation
IUnknown is actually implemented in the original class.
In each nested class definition, addRef, release, queryinterface all calls public addRef defined in the original class.
In the queryinterface function, according to the incoming interface ID, return to the address of the interface member (M_DictionaryObj et al.).
The above structure can construct a COM interface, but writing and maintenance difficulties.
The MFC uses a lot of macro to simplify the nested writing. Due to the use of macros, in the form, there is some acquaintance with the message mapping, but it actually encodes or nested.
3 Implement the class factory. Objects in the class factory.
In the third, the interface definition
Ide
1 In a class, contain multiple interfaces, there is a plurality of nested classes, and QueryInterface is multi-judgment.
It can be abstracted into an array data type (mapping table), and the add interface is simplified to add an item, and the query interface is simplified to the surfaction table.
2 The writing of nested classes is complex, simplified by macro definition.
3 establish a general class factory
2. Implementation
1 Adding an interface mapping table (Declare_Interface_map) in the class definition, add a mapping table in the implementation to fill in the table begin_interface_map, end_interface_map, etc.
The table item includes the interface identification (IID), the location of the interface member (offset of relative object start addresses)
2 Nested class definition macro begin_interface_part, End_Interface_part_static, etc.
2 Class Definitions include universal class members ColeObjectFactory FactFactory Factory, and COM object identifier members GUID, which is completed by Hong Declare_Olecreate
3. Example:
The interface structure is defined.
definition:
Class CDICTIONARYOBJ: PUBLIC CCMDTARGET // is derived from ccmdtarget, and ccmdTarget provides interface-related support.
{
Declare_DyncReate (CDICTIONARYOBJ) // Dynamically created, the class is to dynamically create objects, so it is necessary.
...
Declare_olecreate (cDictionaryObj) // Add type factory member, COM object identity member.
Declare_interface_map () // Add the declaration of the interface mapping table, as well as the declaration of the relevant function.
// Record the interface implemented with this table, and the location of the interface, etc.
// Nested statement
Begin_INTERFACE_PART (Dictionary, iDictionary) // AddRef, Release, etc. The declaration is included in the macro.
Init_Interface_part (CDictionary, Dictionary)
STDMETHOD_ (BOOL, INITIALIZE) ();
...
END_INTERFACE_PART_STATIC (Dictionary)
// Second nested class
Begin_Interface_part (SpellCheck, ISPELLCHECK)
INIT_INTERFACE_PART (CDICTIONARY, SPELLCHECK) stdmethod_ (bool, checkword) (lpolestr, lpolestr *);
END_INTERFACE_PART_STATIC (SPELLCHECK)
...
}
achieve:
Implement_dyncreate (CDICTIONARYOBJ, CCMDTARGET)
// Interface ID
EXTERN "C" const same IID_DICTIONARY =
{0x54BF6568, 0x1007, 0x11d1,
{0xB0, 0xAA, 0x444, 0x45, 0x53, 0x54, 0x00, 0x00}};
EXTERN "C" const Iid IID_SPELLCHECK =
{0x54BF6569, 0x1007, 0x11d1,
{0xB0, 0xAA, 0x444, 0x45, 0x53, 0x54, 0x00, 0x00}};
// Fill in the interface mapping table
Begin_Interface_map (CDICTIONARYOBJ, CCMDTARGET)
Interface_part (cDictionaryObj, IID_Dictionary, Dictionary)
Interface_part (CDICTIONARYOBJ, IID_SPELLCHECK, SPELLCHECK)
END_INTERFACE_MAP ()
// Class Factory implementation, GUID's assignment.
// {54BF6567-1007-11D1-B0AA-444553540000}
Implement_olecreate (CDICTIONARYOBJ, "Dictionary.Object",
0x54BF6567, 0x1007, 0x11d1, 0x1007, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00)
// Realization of each function
STDMETHODIMP_ (ULONG) CDICTIONARYOBJ :: xDictionary :: addRef ()
{
Y) // Define the PTHIS pointer in the macro, and the offset recorded in the interface mapping table calculates the pointer of the COM object, and calls the object class member.
Method_Prologue_ex_ (CDICTIONARYOBJ, DICTIONAR
Return (Ulong) pTHIS-> ExternalAddRef (); // Call the implementation of IUNKNOWN in the CCMDTARGET base class.
// In the case of aggregation, the ExternalAddref calls the implementation of the external iUnknownd
// Usually, INTERNALADDREF is called.
}
STDMETHODIMP CDICTIONOBJ :: xDictionary :: queryinterface
REFIID IID, LPVOID * PPVOBJ)
{
Method_Prologue_ex_ (CDICTIONARYOBJ, DICTIONARY)
// Interface query directly calls the implementation of CCMDTarget, where the interface map is known.
Return (HRESULT) PTHIS-> EXTERNALQUERYINTERFACE (& IID, PPVOBJ);
}
...
[Back to previous points]