Zhao Xiangning
Download this article code
This article provides a complete (DLL) COM server that is fully implemented with C , not allowing ATL or MFC to provide any support. Writing a COM object in this way allows you to insight into the COM processing process and how COM is created. This simple frame with this article You can achieve very basic COM components, such as shell extensions, and so on. If you find any questions during use, feed it back to vckbase@public.hk.hi.cn.
The following is the step of writing your own COM object in the way in this article:
Step 1: Write a header file, this header file contains the following:
1, contain file comdef.h: #include
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. Give the IID of the interface and the method defined by this interface to be implemented. When the client will use the IID and interface of this interface.
Interface __declspec (UUID ("F614FB00-6702-11D4-B0B7-0050BABFC904")) IMYINTERFACE: Public IUNKNOWN
{
STDMETHOD (long) (long * pval) Pure;
STDMETHOD (CUBE) (long * pval) Pure;
}
The client uses this interface:
HRESULT HR;
ImyInterface * pmine = (0);
HR = CoCreateInstance (CLSID_MINE, // COM server CLSID
NULL, / / do not support aggregation
CLSCTX_INPROC_SERVER, / / is a DLL
__UUIDOF (ImyInterface), // interface IID
(void **) & pmine
);
Another way can get the CLSID of the COM object from the registry, which is called the clsidFromProgID () function, but the component's progID must be passed to this function.
Step 2: The implementation must be implemented for the defined interface, the method of this paper is to create a new class inherited from the interface:
// This class implements single port ImyInterface ...
//
//
Class CMYINTERFACE: Public CCOSE <>,
Public InterfaceImpl
{
PUBLIC:
CMYINTERFACE ();
Virtual ~ cmyinterface ();
/ / We must write code for QueryInterface
STDMETHOD (QueryInterface) (Refiid Riid, LPVOID * PPV);
// ImyInterface interface method
STDMETHOD (long * pval);
STDMETHOD (CUBE) (long * pval);
}
Model InterfaceImpl <> provides an implementation of the interface reference count. Here we can inherit with multiple interfaces, which can implement multiple interfaces in a COM component.
Step 3: Before completing this object, we have to write queryinterface and two interface methods:
STDMETHODIMP CMYINTERFACE :: Queryinterface (Refiid Riid, LPVOID * PPV)
{
* ppv = NULL;
IF (ISEqualiid (RIID, IID_IUNKNOWN) || ISEQUALID (RIID, __ uuidof (iMyInterface)))
{
// Because we inherit from ImyInterface, it is necessary to convert the mandatory type conversion
* PPV = (iMyInterface *).
_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 * value;
Return S_OK;
}
Note that the __UUIDOF (ImyInterface) is used to get the IID of the interface because we have already associated this interface to a UUID in the first step.
The last step: The DLLS of the COM component must output a function called DllgetClassObject. Create a class plant for CMYINTERFACE and return a reference to it. Then we call CocreateInstance to create a class factory in the process, then call DllgetClassObject. This class factory has a method to create inStance, created objects by this method and returns a reference to it.
Stdapi DllgetClassObject (Refclsid Rclsid, Refiid Riid, LPVOID * PPVOUT)
{
* ppvout = NULL;
IF (ISEqualiid (Rclsid, CLSID_MINE))
{
/ / For the CMYINTERFACE Class Declaration Factory
CCLASSFACTORY
* pcf = new cccoassfactory
Return PCF-> QueryInterface (RIID, PPVOUT);
}
Return Class_e_classNotavailable;
}
Here we have to check whether the requested CLSID is CLSID_MINE, if not, an error code is returned.
You may ask where to create a practical CMYINTERFACE class object, in fact, this is handled by a template instance of CCLASSFAACTORY
// CSINGLREATOR is used in a single real example factory, which returns the same object pointer for multiple CREATEOBJECT requests..
Template
Class CsinglecReator
{
protected:
CSINGLECREATOR (): m_pobj (0) {};
Comobj * createObject ()
{
IF (! m_pobj)
{
m_pobj = new como.bj;
}
Return M_POBJ;
}
COMOBJ * M_POBJ;
}
// cmulticreator is used for common class factories, which returns new object pointers for each CreateObject request..
Template
Class Cmulticreator
{
protected:
CMULTICREATOR (): m_pobj (0) {};
Comobj * createObject ()
{
Return new comobj;}
COMOBJ * M_POBJ;
}
// ClassFactory class implementation
// Multicreator is the default factory creator
// This class implements the interface iClasFactory ......
Class CclassFactory: Public CCOMBASE <>,
Public InterfaceImpl
Public CreatorClass
{
PUBLIC:
CCLASSFACTORY () {};
Virtual ~ cclassfactory () {};
STDMETHOD (QueryInterface) (Refiid Riid, LPVOID * PPV)
{
* ppv = NULL;
IF (ISEqualiid (RIID, IID_IUNKNOWN) || ISEQUALID (RIID, IID_ICLASSFAACTORY))
{
* ppv = (iClassFactory *).
_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 = creteObject (); // m_pobj defines 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
}
CREATEINSTANCE Create a request object, the parameter RIID refers to the requested interface IID, if this object supports this interface, add its reference count and return to its own reference.
About code: How to write a big concept of COM components with pure C . Many details are omitted. From the text and code of this article, you can see what you need to do with pure C COM components. If you want to write COM components in this way, these code can only be thrown into jade, and the specific implementation can be on this basis. Make it ........