COM in-depth understanding (on) - Method parameter type is cruntimeclass *, void *, etc. often see how to send VOID * or a custom class, such as Class Ca; Ca *, etc. This article describes how to pass a custom class object on COM, and clarify the role of MIDL to illustrate it is not necessary. Note that the customized type of customized types in this article is not the same concept without any relationship with the customized type of automation technology (iDispatch). COM service provides the essence of the mathematical model is a service provider. Like DLL (Dynamic Library Technology), it is an external service. In a sense, this is also called code reuse, but it should be cleared The difference between code - code reuse is just a way of providing services, which is also the purpose of the DLL. DLL defines a section in this format in its PE format (Portable Executable Format, a file format, EXE, DLL, OBJ, etc.) (section, a continuous storage space), called the Export Section . In this section, the relative virtual address of the entry code of each export function in the current DLL file is recorded, which is equivalent to a function address. When this DLL file is mapped to the virtual memory space of the load process, the thread can jump to the DLL's export function entry to the DLL export function entry according to the relative virtual address in the Export section. The code that exported the function is reused at this time. In the above implementation, the DLL functional export method is static export (even if the function address is changed due to the requirements of the file mapping, but the function address is changed during its entire load period). COM is completely different, which is dynamically exported, that is, the first-level pointer, the customer is not a function pointer, but the function pointer array, although the DLL's export section is also equivalent to the function pointer array, but COM here again Add a first-level packaging, get dynamic through a function pointer argument by a function pointer built on a stack or stack, not a read-only type (top multi-on-write) memory like the DLL export section (although not The focus is only one. The previously mentioned function pointer array represents an interface that often hearses in the implementation of COM. And the function of the dynamic function pointer, the COM running period provides a function to implement - CogetClassObject, which returns the first function pointer array (interface) used by the customer, which is very similar to getProcAddress, but after Only returns a function pointer, and the former returns the function pointer array. Since the return function pointer array is to pass a pointer (ie, the pointer to the function pointer is transferred, not what API is called), so this method can be applied to anywhere, including a function of the interface export. IUNKNOWN :: QueryInterface in COM is specifically used for this service. Since the virtual function implementation mechanism provided by C also has a function pointer array, when writing COM components with C , the interface is generally represented by a pure virtual basis. In C, since there is no concept of virtual functions, the structure is used to define a function pointer array. The implementation of the C class is binary code, that is, the machine code is a concept of category.
However, COM is a service based on binary basis, so the implementation of classes in C will be described below. The class is actually a function of continuous memory and some functions executing on this memory block, and this consecutive memory block is an instance of a structure, and the member function is actually only one of the names of this structure as THIS. C function. As the following class definition: Class Ca {long a; public: ca (): a (0) {} long geta () {RETURN A;}}; CA AA; long a = aa.geta (); It actually: Struct s_ca {long a;}; long s_ca_geta (s_ca * this) {Return this-> a;} void s_ca_ca (s_ca * this) {this-> a = 0; // Assumeout no optimization switch} s_ca s_aa; S_CA_CA (& S_AA); Long A = S_CA_GETA (& S_AA); therefore, the class is actually a structure and some related functions, the purpose of its existence is to facilitate the writing of the code and introduce semantics to provide support for programming ideas. When the class has a virtual function, like the above, only one member is more than one member specifically records a function pointer array, representing all the virtual functions of this class, which is also the implementation form of the COM interface. As follows: Class Ca {Long a; public: CA (): a (0) {} Virtual long geta () {RETURN A;} Virtual void seta (long var) {a = var;}}; ca Aa; long A = aa.geta (); aa.seta (34); becomes: struct s_ca_d; struct s_ca_f // is equivalent to a function pointer of only two elements {long (* Geta) (S_CA_D *); Void (* seta (S_ca_d *, long);}; struct s_ca_d {s_ca_f * pf; long a;}; long s_ca_geta (s_ca_d * this) {Return this-> a;} void s_ca_seta (s_ca_d * this, long var) {this- > a = var;} S_CA_F G_S_CA_F = {S_CA_GETA, S_CA_SETA}; Void S_CA_CA (S_CA_D * this) {this-> PF = & g_s_ca_f; // Set virtual function pointer this-> a = 0; // assume no optimization Switch} S_CA_D S_AA; S_CA_CA (& S_AA); long a = (s_aa.pf-> geta) (& S_AA); (S_AA.PF-> Seta) (& S_AA, 34); non-MIDL supported parameters to pass the C Class After the implementation method, it is necessary to pass a class pointer. It is actually transmitted a struct pointer, and the problem in the forum is always the error compiled when MIDL compiles. The "Type undefined" is always said. Let's understand the MIDL's role.
MIDL is just a compiler with a code provided by Microsoft's IDL (Interface Definition Language, Interface Definition Language) or ODL (Object Definition Language, Object Definition Language). After this compiler compiles. IDL or .odl file, generate a type library (if necessary) and proxy / placeholder components (about the agent / placeholder component can refer to another article "COM Thread Model") file. When MIDL generates a proxy / placeholder component for COM (or RPC), its generated engineering file includes: xxx_i.c, xxx_p.c, dlldata.c, xxx.h and an make file xxxps.mk (VC The generation tool NMAKE program can use this file) to help generate proxy / placeholder components (which are compiled .idl file names xxx.idl). It should be noted that this agent / placeholder component does not have to be required, and it only occurs when it is required (such as the interface pointer to make a collection operation, the component request call environment, etc.), in addition to any time there is no action. Therefore, if you can guarantee that the generated component will not be called between the spans or does not require COM to provide additional functions (such as calling CogetherCallContext), the consequence of the agent / placeholder component is the application of this COM component. The range is severely restricted (which is equivalent to a DLL, but still has a dynamic providing service), when needed, if the defensive code is not written, the program is likely to crash. The following example shows how to write a COM component equivalent to the DLL and does not require .idl file. The following interfaces are to be achieved: interface IModule: IUnknown {HRESULT GetViewRuntimeClass ([out] CRuntimeClass ** pClass);}; because they have no MIDL nagging, so also follows: interface IModule: IUnknown {HRESULT GetViewRuntimeClass ([out] CruntimeClass ** PCLASS; void getModulen ([out] cstring * pname;}; manual generation one .h file, as follows: /ModuleInterface.h /// # pragma overce # include
/PopedomModule.h/#pragma onceclass ATL_NO_VTABLE CPopedomModule: public CComObjectRootEx