Compile COM components with pure C ++

Source: Internet
Author: User
Zhao Xiangning

Download this article code
This document provides an in-process (DLL) COM server fully implemented using C ++. Do not use ATL or MFC to provide any support. Writing COM objects in this way can give you a deep insight into the methods used by com to process servers in the process and how com creates a class factory. Using the simple framework provided in this article, you can implement basic COM components, such as shell extensions. If you find any problem during use, feed it back to the vckbase@public.hk.hi.cn.

The following are the steps to compile your own COM object in the method described in this article:

Step 1: Write a header file that contains the following content:
1. Include the file comdef. h: # include <comdef. h>.
2. Define the guid of the COM server.
_ Declspec (selectany) guid clsid_mine = {0xdc186800,
0x657f,
0x11d4,
{0xb0, 0xb5, 0x0, 0x50, 0xba, 0xbf, 0xc9, 0x4}
};

3. Provide the IID of the interface and the method definition to be implemented for this interface. Then the client will use the IID and method of this interface.
Interface _ declspec (UUID ("F614FB00-6702-11d4-B0B7-0050BABFC904") imyinterface: Public iunknown
{
Stdmethod (square) (long * pval) pure;
Stdmethod (cube) (long * pval) pure;
};

The client uses this interface:
Hresult hr;
Imyinterface * pmine = (0 );
HR = cocreateinstance (clsid_mine, // CLSID of the COM Server
Null, // does not support Aggregation
Clsctx_inproc_server, // is a DLL
_ Uuidof (imyinterface), // The IID OF THE INTERFACE
(Void **) & pmine
);

Another way is to obtain the CLSID of the COM object from the registry, that is, call the clsidfromprogid () function, but you must pass the progid of the component to this function.

Step 2: You must provide implementation for the defined interface. The method used in this article is to create a new class inherited from the interface:

// This class implements a single interface imyinterface...
//
//
Class cmyinterface: Public ccombase <>,
Public interfaceimpl <imyinterface>
{
Public:
Cmyinterface ();
Virtual ~ Cmyinterface ();

// We must write code for QueryInterface
Stdmethod (QueryInterface) (refiid riid, lpvoid * GMM );

// Imyinterface Interface Method
Stdmethod (square) (long * pval );
Stdmethod (cube) (long * pval );

};

The template class interfaceimpl <> provides the implementation of interface reference count. Here we can use multi-interface inheritance to implement multiple interfaces in a COM component.

Step 3: before completing this object, we also need to write QueryInterface and two interface methods:
Stdmethodimp cmyinterface: QueryInterface (refiid riid, lpvoid * bp)
{
* GMM = NULL;
If (isequaliid (riid, iid_iunknown) | isequaliid (riid ,__ uuidof (imyinterface )))
{
// Force type conversion is required because we inherit from imyinterface
* GMM = (imyinterface *) This;

_ Addref (); // This method is inherited from a base class.
Return s_ OK;
}
Return e_nointerface;
}

Stdmethodimp cmyinterface: Square (long * pval)
{
Long value = * pval;
* Pval = value * value;
Return s_ OK;
}

Stdmethodimp cmyinterface: Cube (long * pval)
{
Long value = * pval;
* Pval = value * value;
Return s_ OK;
}

Note that _ uuidof (imyinterface) is used to obtain the IID of the interface, because we have associated this interface with a uuid in the first step.

Last step: the DLLs of the COM component must output a function called dllgetclassobject. This function creates a class factory for cmyinterface and returns a reference to it. Then we call cocreateinstance to create a class factory for COM in the process, and then call dllgetclassobject. A method of this class factory is createinstance, which creates an object and returns a reference to it.
Stdapi dllgetclassobject (refclsid rclsid, refiid riid, lpvoid * ppvout)
{
* Ppvout = NULL;
If (isequaliid (rclsid, clsid_mine ))
{
// Declare a factory for the cmyinterface class
Cclassfactory <cmyinterface>
* PCF = new cclassfactory <cmyinterface>;
Return PCF-> QueryInterface (riid, ppvout );
}
Return class_e_classnotavailable;
}

Check whether the requested CLSID is clsid_mine. If not, an error code is returned.
You may ask where to create the actual cmyinterface class object. In fact, this is handled by the template instance of cclassfactory <cmyinterface>. The following is the implementation of cclassfatory:

// Csinglecreator is used for a single instance class factory. This class returns the same object pointer for multiple Createobject requests ..
Template <class comobj>
Class csinglecreator
{
Protected:
Csinglecreator (): m_pobj (0 ){};

Comobj * Createobject ()
{
If (! M_pobj)
{
M_pobj = new comobj;
}
Return m_pobj;
}
Comobj * m_pobj;
};

// Cmulticreator is used in common class factories. This class returns a new object pointer for each Createobject request ..
Template <class comobj>
Class cmulticreator
{
Protected:
Cmulticreator (): m_pobj (0 ){};
Comobj * Createobject ()
{
Return new comobj;
}
Comobj * m_pobj;
};

// Classfactory class implementation
// Multicreator is the default class factory creator.
// This class implements the interface iclasfactory ......

Class cclassfactory: Public ccombase <>,
Public interfaceimpl <iclassfactory>,
Public creatorclass
{
Public:
Cclassfactory (){};
Virtual ~ Cclassfactory (){};

Stdmethod (QueryInterface) (refiid riid, lpvoid * GMM)
{
* GMM = NULL;
If (isequaliid (riid, iid_iunknown) | isequaliid (riid, iid_iclassfactory ))
{
* GMM = (iclassfactory *) This;
_ Addref ();
Return s_ OK;
}
Return e_nointerface;
}

Stdmethodimp createinstance (lpunknown punkouter, refiid riid, lpvoid * ppvobj)
{
* Ppvobj = NULL;
If (punkouter)
Return class_e_noaggregation;
M_pobj = Createobject (); // m_pobj is defined in creatorclass
If (! M_pobj)
Return e_outofmemory;
Hresult hR = m_pobj-> QueryInterface (riid, ppvobj );
If (HR! = S_ OK)
{
Delete m_pobj;
}
Return hr;
}

Stdmethodimp lockserver (bool) {return s_ OK;} // not implemented
};

Com calls createinstance to create the requested object. The riid parameter refers to the requested interface IID. If this object supports this interface, it will increase its reference count and return its reference to itself.

Code: the method proposed in this article is to use pure C ++ to compile a big concept of COM components. Many details are omitted. From the text and code in this article, we can see what needs to be done to write COM components in pure C ++. If you want to write COM components in this way, these codes can only be used as a reference, the specific implementation can be done on this basis ........

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.