A Preliminary Study on COM technology (I)

Source: Internet
Author: User
Tags import database
1. com is a better C ++
1. What is com?
2. From C ++ to DLL and then to com
2.1 C ++
2.2 DLL
2.3 com

Ii. com Basics
1. Basic knowledge of COM
1.1 return value hresult
1.2 first recognized IDL
1.3 iunkown Interface
2. a relatively simple com
2.1 interface. h file
2.2 math. h file
2.3 math. cpp File
2.4 simple. cpp File
2.5 binary structure of math component
Conclusion 2.6

3. Create a COM component manually
1. From Project Creation to registration
1.1 create a Win32 DLL Project
1.2 define interface file
1.3 added the registration function
1.3.1 Add a mathcom. Def File
1.3.2 dllregisterserver () and dllunregisterserver ()
1.4 mathcom. cpp File
Conclusion 1.5
2. Implement ismiplemath, iadvancedmath, and dllgetclassobject ()
2.1 implement ismiplemath and iadvancedmath Interfaces
2.2 general process of calling COM components
2.3 dllgetclassobject () Implementation
2.4 Client
Conclusion 2.5
3. Category Factory

Appendix
A. My Understanding of DLL
1. DLL without lib
1.1 create a DLL without lib
1.2 debug a DLL without lib
2. dll with LIB
2.1 create a DLL with LIB
2.2 debug a DLL with reference but no header file
3. dll with header file
3.1 create a DLL with the header file
3.2 debug a DLL with a header file
Iv. Summary

1. com is a better C ++

1. What is com?

Don box says "com is love ". Com is the component object model of Component Object Model.

2. From C ++ to DLL and then to com

2.1 C ++

If a software vendor releases a class library (cmath arithmetic operation), the executable code of the class library will become an integral part of the customer's application. Assume that the machine code generated by such libraries occupies 4 MB space in the target executable file. When all three applications use the cmath library, each executable file contains 4 MB class library code (see Figure 1.1 ). When the three applications run together, they will occupy 12 Mb of virtual memory. The problem is far from that. Once the class library vendor discovers that the cmath class library has a defect, it releases a new class library and requires all applications that use this class library. In addition, there is no other way.




Figure 1.1 three customers of cmath

2.2 DLL

One technique to solve the above problem is to encapsulate the cmath class into a dynamic link library (DLL, dynamic link library.
When using this technology, all the methods of cmath will be added to the export list of cmath DLL, And the linker will generate an import library ). This library exposes the symbol of the cmath method member. When the customer links to import data into the database, some stubs will be introduced into the executable file, which notifies the loader to dynamically load the cmath DLL at runtime.
When cmath is in DLL, its running model is shown in Figure 1.2.


Figure 1.2 cmath import database

2.3 com

"Simple introduction of C ++ class definitions from DLL" does not provide a reasonable binary component structure. C ++ class is both an interface and an implementation. In this case, the interface must be separated from the implementation to provide the binary component structure. In this case, there must be two C ++ classes, one as the interface class and the other as the implementation class. Let's get started with COM.

Ii. com Basics

1. Basic knowledge of COM

1.1 return value hresult

Com requires that all methods return an error code of the hresult type. Hresult is actually defined as a Type:

    typedef LONG HRESULT;

For hresult definitions, see the winerror. h file.

//  Values are 32 bit values layed out as follows:////  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0//  +-+----+-------------------------+---------------------------------+//  |S| Res|     Facility            |     Code                        |//  +-+----+-------------------------+---------------------------------+////  where////      S - is the severity code////          0 - Success//          1 - Error////      Res- is a reserved bit////      Facility - is the facility code////      Code - is the facility''s status code

We generally use the following macro to determine whether the method is successful:

#define SUCCEEDED(hr)(long(hr)>=0)#define FAILED(hr)(long(hr)<0)

1.2 first recognized IDL

Each standard COM component requires an interface definition file with the extension of IDL. Let's take a look at the definition file of the iunknow interface.

[Local, object, UUID (00000000-0000-0000-c000-000000000046), pointer_default (unique)] interface iunknown {typedef [unique] iunknown * lpunknown; cpp_quote ("///////////////////////////////////// /////////////////////////////") cpp_quote ("// iid_iunknown and all other system IIDS are provided in UUID. lib ") cpp_quote (" // link that library in with your proxies, clients and servers ") cpp_quote ("/////////////// //////////////////////////////////////// ///////////") Hresult QueryInterface ([in] refiid riid, [out, iid_is (riid)] void ** ppvobject); ulong addref (); ulong release ();} the [local] attribute prohibits the generation of network code. The [object] attribute indicates that a COM interface is defined, rather than an Dec-style interface. The [UUID] attribute gives the interface a guid. The [unique] attribute indicates that the null (null) pointer is a valid parameter value. [Pointer_defaul] specifies a default pointer attribute typedef [unique] iunknown * lpunknown for all embedded pointers in the attribute. This is an interesting type definition cpp_quote, which is a method for writing annotations in The IDL file. These annotations will be saved ***. H and *** _ I. in the c file, [in] indicates that this parameter is an input parameter [out], indicating that this parameter is an output parameter [iid_is (riid)], indicating that this parameter requires the previous riid parameter.

Note: All parameters with the out attribute must be pointer type.

1.3 iunkown Interface

In the entire example, except for the iunkown, other things should not be unfamiliar! Com requirements (the most basic requirements) All interfaces must be directly or indirectly inherited from the iunknown interface. Therefore, the iunknown interface is called "the source of all evil.
The iunkown interface defines three methods.

HRESULT QueryInterface([in] REFIID riid,[out] void **ppv);ULONG AddRef();ULONG Release();    

Addreft () and release () are used for object reference counting, while the QueryInterface () method is used for querying the Implemented interfaces. The addref () method should be called every time the COM component is referenced. When the client releases an interface of the COM component, it needs to call the release () method.
For more information, see the following example.

2. a relatively simple com

This example consists of four files:
 

File Name Description
Interface. h Interface class definition file
Math. h and math. cpp Implementation class file
Simple. cpp main function File It is used as a COM Client.

2.1 interface. h file

#ifndef INTERFACE_H#define INTERFACE_H#include <unknwn.h>//{7C8027EA-A4ED-467c-B17E-1B51CE74AF57}static const GUID IID_ISimpleMath = { 0x7c8027ea, 0xa4ed, 0x467c, { 0xb1, 0x7e, 0x1b, 0x51, 0xce, 0x74, 0xaf, 0x57 } };//{CA3B37EA-E44A-49b8-9729-6E9222CAE84F}static const GUID IID_IAdvancedMath = { 0xca3b37ea, 0xe44a, 0x49b8, { 0x97, 0x29, 0x6e, 0x92, 0x22, 0xca, 0xe8, 0x4f } };interface ISimpleMath : public IUnknown{public:virtual int Add(int nOp1, int nOp2) = 0;virtual int Subtract(int nOp1, int nOp2) = 0;virtual int Multiply(int nOp1, int nOp2) = 0;virtual int Divide(int nOp1, int nOp2) = 0;};interface IAdvancedMath : public IUnknown{public:virtual int Factorial(int nOp1) = 0;virtual int Fabonacci(int nOp1) = 0;};#endif    

This file first # include <unknwn. h> to include the iunknown interface definition file.
Next, two interfaces are defined. GUID (globally unique identifier of globally unique identifier) can ensure the uniqueness of time and space.
The ismiplemath interface defines four methods, while the iadvancedmath interface defines two methods. These methods are virtual functions, and the entire ismiplemath and iadvancedmath abstract classes serve as binary interfaces.

2.2 math. h file

#include "interface.h"class CMath : public ISimpleMath,  public IAdvancedMath{private:ULONG m_cRef;private:int calcFactorial(int nOp);int calcFabonacci(int nOp);public://IUnknown MethodSTDMETHOD(QueryInterface)(REFIID riid, void **ppv);STDMETHOD_(ULONG, AddRef)();STDMETHOD_(ULONG, Release)();//ISimpleMath Methodint Add(int nOp1, int nOp2);int Subtract(int nOp1, int nOp2);int Multiply(int nOp1, int nOp2);int Divide(int nOp1, int nOp2);//IAdvancedMath Methodint Factorial(int nOp);int Fabonacci(int nOp);};    

This class is an implementation class, which implements two interface classes: ismilelemath and iadvancedmath (of course, only one interface class can be implemented ).
Note: m_cref is used to count objects. When m_cref is 0, the component object should be automatically deleted.

2.3 math. cpp File

# Include "interface. H "# include" math. H "stdmethodimp cmath: QueryInterface (refiid riid, void ** GMM) {// This is the function for implementing dynamic_cast, but because dynamic_cast is related to the compiler. If (riid = iid_isimplemath) * GMM = static_cast
 (This); else if (riid = iid_iadvancedmath) * bp= static_cast
 (This); else if (riid = iid_iunknown) * GMM = static_cast
 (This); else {* GMM = 0; return e_nointerface;} reinterpret_cast
 (* GMM)-> addref (); // The reference count is for the return s_ OK;} stdmethodimp _ (ulong) cmath: addref () {return ++ m_cref;} stdmethodimp _ (ulong) cmath: release () {ulong res = -- m_cref; // use temporary variables to cache the modified reference count value if (RES = 0) // because it is invalid to delete this; return res;} int cmath: add (INT nop1, int nop2) when the object is destroyed and then referenced) {return nop1 + nop2;} int cmath: Subtract (INT nop1, int nop2) {return nop1-nop2;} int cmath: multiply (INT nop1, int nop2) {return nop1 * nop2;} int cmath: Divide (INT nop1, int nop2) {return nop1/nop2;} int cmath: calcfactorial (int nop) {If (NOP <= 1) return 1; return NOP * calcfactorial (NOP-1);} int cmath: factorial (int nop) {return calcfactorial (NOP );} int cmath: calcfabonacci (int nop) {If (NOP <= 1) return 1; return calcfabonacci (NOP-1) + calcfabonacci (NOP-2);} int cmath :: fabonacci (int nop) {return calcfabonacci (NOP);} cmath: cmath () {m_cref = 0 ;}

This file is a cmath class definition file.

2.4 simple. cpp File

# Include "math. H "# include <iostream> using namespace STD; int main (INT argc, char * argv []) {isimplemath * psimplemath = NULL; // declare the interface pointer iadvancedmath * padvmath = NULL;
 
 
 
 // Create an object instance. Now we create an object instance. com has the mechanism of creating an object instance. cmath * pmath = new cmath;
 
 
 
 // Interface implemented by the query object isimplemathpmath-> QueryInterface (iid_isimplemath, (void **) & psimplemath); If (psimplemath) cout <"10 + 4 =" <psimplemath-> Add (10, 4) <Endl;
 
 
 
 // Iadvancedmathpsimplemath-> QueryInterface (iid_iadvancedmath, (void **) & padvmath); If (padvmath) cout <"10 fabonacci is" <padvmath-> fabonacci (10) <Endl; padvmath-> release (); psimplemath-> release (); Return 0 ;}

This file is equivalent to the client code. First, create a cmath object and then query the required interface based on the object. If the required interface pointer is obtained correctly, call the interface method, finally, release the interface.

2.5 binary structure of math component


Figure 1.3 binary structure of math Components

Conclusion 2.6

In a strict sense, this example is not a true COM component (he is not a DLL), but he has met the minimum requirements of COM (implementing the iunknown interface ). Next we will create a com DLL (but not ATL ).

 

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.