Discussion on Event Driver Technology in COM
Zou Fei
Version V1.0
July 2004
table of Contents
1. The question is proposed .... 3
2. Finite term .... 3
3. Common technology .... 3
3.1 Tight Coupling Events (TCE) ... 3
3.1.1 connection technology ... 3
3.1.2 Message Queue Technology ... 11
3.2 Loose Coupled Events (LCE) ... 11
3.2.1 Event Drives of Com
4. Summary ... 18
1. Problem
Similar to the OBServer mode in the design mode, in COM programming, it is desirable to implement a mechanism to enable a number of parts that are interested in data to accept changes in data. A typical application: Computer Monitor Notifys system administrators, system log programs, email, and more when computer status data changes.
2. Finite term
Subscriber Subscriber: Programs interested in data
Publisher Publisher: Program for issuing data change notifications
Exciting event firing event: the notification process initiated by the publisher
Source Interface (OUTGOING) Interface: Consistent Interface Decided between Publisher and Subscribers
Receiver (SINK): Subscriber provides objects to the publisher
3. Common technology
3.1 Tight Coupling Events (TCE)
3.1.1 Connection Point Technology
A technique for connecting points is provided in COM for implementing event drivers.
The connection point technology is:
N subscribers pass the query standard COM interface iconnectionPointContainer, ask if the publisher supports the connection point mechanism
n Get a specific type of connection point through the FindConnectionPoint method of IconnectionPointContainer, returning by interface iconnectionpoint
n subscriber Create a receiver (SINK) object
n Subscribe Add a Cookie (DWORD ID) by adding the receiver object to the publisher's recipient list.
N subscribers cancel the attention of the event through the unadvise of IconnectionPoint
From the above working method, you can find that the connection point technology is to be implemented, as long as the subscriber and the publisher follow certain interface specifications, and the interface is implemented.
Publisher: Realize the container of IconnectionPointContainer, support connection point of IconnectionPoint
Subscriber: Implement SINK object
In VC, a variety of mechanisms have been simplified for the implementation of the connection point, making it easy to develop the connection point program, which has good support for the connection point in VC6 and VC7, and there is a difference, this article Introduce.
Example introduction
First introduce the functional description of the instance we want to implement:
Publisher: Implement an address of an add method, when the add method is called, if the result is greater than 100, call the ONADD event, pass the ADD parameters, and implement the DLL of a COM.
Subscriber: Subscribe to the ONADD event, when the onAdd event is called, the output parameter value is implemented as Dialog Based Application. Visual C 6.0
Visual C provides ATL (Active Template Library, Activity Templank) from 5.0, which can be used to develop a developer of lightweight COM components (using very complex Template in ATL, it is very troublesome to understand ~~ ~)
Our first way is to achieve connection points through ATL:
announcer:
N New COM components via ATL COM Wizard
Project name is XADD
n Create a new COM object via ATL Object Wizard (Simple Object)
Short name is set to add (other name Wizard is automatically generated), and supports Support Connection Points in Attributes in Attributes so that the COM object supports the connection point, which automatically generates an_iaddevents interface.
N to add add methods to add
HRESULT ADD ([in] long A, [in] long b, [out] long * pVAL);
N to _iaddevents Add ONADD Method
HRESULT ONADD ([in] long A, [in] long b);
N f7 compiled, automatically register COM components
N Select Implement Connection Point in CADD 's Right-click Menu, Select_Iaddevents
Wizard will automatically add the implementation of the IconnectionPointContainer interface to CADD, and increase CPROXY_IADDEVENTS, which is implemented for the IconnectionPoint interface.
N Increase the trigger of the event in the ADD method implementation of CADD:
STDMETHODIMP CADD :: Add (long A, long b, long * pval)
{
* pval = a b;
Fire_onadd (a, b); // Trigger ONADD event
Return S_OK;
}
N recompile, register.
subscriber:
n Newly built an MFC AppWizard (EXE), named xaddclient, type Dialog Based, the rest is default.
n Support for ATL (a simple way is to select New ATL Class, because you cannot join the ATL Class in the MFC Application, but this is ATL support has been added)
n Add XADD.H file in the project (publisher's interface definition header file)
n Type library for importing COM in the project
Join in stdafx.h:
#import "../xadd.tlb" NO_NAMESPACE, NAMED_GUIDS
n Newly built a class CEVENTSINK, PUBLIC inherits from IdispeventImpl <1, CEVENTSINK, & DIID__IADDEVENTS, & LIBID_XADDLIB>
Namespace {
_TL_FUNC_INFO ONADDINFO =
{
CC_STDCALL,
VT_EMPTY,
2 ,
{Vt_i4, vt_i4}
}
}
Class Ceventsink: Public IdispeventImpl <1, CEVENTSINK, & DIID__IADDEVENTS, & LIBID_XADDLIB>
{
PUBLIC:
CEVENTSINK ();
Virtual ~ ceventsink ();
Void __stdcall onadd (int A, int b);
Begin_sink_map (Ceventsink)
SINK_ENTRY_INFO (1, DIID__IADDEVENTS, 1, ONADD, & OONADDINFO)
END_SINK_MAP ()
}
N to achieve CEVENTSINK ONADD method
Void __stdcall Ceventsink :: Onadd (int A, int b)
{
CString Str;
Str.Format ("% D% D", A, B);
AfxMessageBox (STR);
}
In this way, the receiver object has been completed, and the receiver Advise is onto the XADD object.
n Add to the Advise of the SINK object in Dialog, and call the add () method, this step is relatively simple, you can refer to the routine
n Define the private variable:
Iaddptr padd;
DWORD DWCOOKIE;
CEVENTSINK * PSINK;
n Create a COM object in OnInitDialog ()
Coinitialize (NULL);
Padd.createInstance (__ uuidof (add));
N Destroy COM objects in DestroyWindow
PADD = NULL;
Couninitialize ();
N Add 3 button Method: Oncalladd, Onadvise, Onunadvise
Void cxaddclientdlg :: oncalladd ()
{
Long Ret;
PADD-> Add (1, 2, & ret);
}
Void cxaddclientdlg :: onadvise ()
{
IF (psink == null)
{
Psink = new ceventsink ();
Atladvise (padd, (iunknown *) psink, diid__iaddevents, & dwcookie;
}
}
Void cxaddclientdlg :: onunadvise ()
{
IF (psink! = null)
{
ATLunadvise (Padd, DiID__iaddevents, dwcookie);
Delete psink;
}
}
We can find that ATL defines a group of wizard, macro, template, etc., making it easy to implement COM objects, we don't need to care about addRef (), release () and other general methods, ATL has helped us well-done.
In addition to using ATL as a development library developing COM, the MFC also provides good COM support, so connection point technology can also be implemented by MFC, this article is no longer introduced.
Visual C 7.0
After Microsoft launched Visual Studio.NET, the VC is also upgraded. In Visual C 7.0, there is a lot of expansion of C , including better support for COM.
In VC 7.0 can be easily implemented by __hook, __ unhook keywords. Here is a specific implementation example (the development environment: Microsoft Visual C . NET Chinese version):
announcer:
N Newly built an ATL project in VC 7.0, named XADD
n Add ATL Simple Object, named Add, add support for connection points in the option:
n Here there is a small problem, and the interface definition automatically generated by Wizard is the (add.h) that is defined with the implementation class of the interface, but the interface definition should be visible, and the implementation class of the interface should not Customers can see, so we make a change, define the interface in add.h to another file Iadd.h, and in add.h #include "add.h"
N Add method add in IADD
HRESULT ADD ([in] long A, [in] long b, [out, retval] long * pval);
N to add event methods in _iaddevents onadd
HRESULT ONADD ([in] long A, [in] long b);
n Implement Add method in CADD
STDMETHODIMP CADD :: Add (long A, long b, long * pval)
{
* pval = a b;
__raise onadd (a, b); // Trigger event
Return S_OK;
}
n compiled, registration
subscriber:
n New WIN32 Console Project, add ATL support in AddClient, application settings
N Add ATL Support
Add: in stdafx.h:
#define _ATL_ATITRIBUTES
#include
#include
#include
n Add class addProxy to implement SINK objects, while acting as a client event
Head file addproxy.h
#pragma overce
#include
#include "../Iadd.h"
[Module (name = "receiver")];
[Event_Receiver (COM)]
Class CaddProxy
{
PUBLIC:
CaddProxy (void);
Virtual ~ CaddProxy (Void);
Void onadd (long A, long b);
Private:
Void Hook (IADD * PS);
Void UnHook (IADD * PS);
Long Add (long A, long b); // Package for COM objects
_COM_SMARTPTR_TYPEDEF (IADD, __UUIDOF (IADD));
Iaddptr m_padd;
}
Implement file addproxy.cpp
#include "stdafx.h"
#include "./addproxy.h"
#include
Using namespace std;
CaddProxy :: CaddProxy (void)
{
m_padd.createInstance ("xadd.add"); // Create a COM object
Hook (m_padd); // Mounting event
}
CaddProxy :: ~ CaddProxy (void)
{
UnHook (m_padd); // Cancel Mount m_padd = null; // Destroy the COM object
}
Void CaddProxy :: Onad (long A, long b)
{
COUT << a << b << endl; // event code
}
Void CaddProxy :: HOOK (IADD * PS)
{
__hook (& _ ipdevents :: onadd, ps, & caddproxy :: onadd); // Mount
}
Void CaddProxy :: UnHook (IADD * PS)
{
__unhook (ps); // Cancel Mount
}
Long CaddProxy :: Add (long A, long b)
{
Long Ret;
m_padd-> add (a, b, & ret);
Return Ret;
}
n Creating an Proxy object in the main () function, execute the add () method.
INT _Tmain (int Argc, _tchar * argv [])
{
CADDPROXY ADD;
Add.Add (1, 2);
Return 0;
}
n compiled, executed.
If we look at Wizard to help us generate the code, we can find that there are many keywords to COM in VC 7.0, such as __event, __ interface, __ raise, __ hook, __ unhook, etc. To implement COM Event driver is very simple (even if Wizard is not used, it is not complicated by manual coding)
In addition, it is necessary to explain that although VC 7.0 is provided in VS.NET, the COM components and receivers written by this method can be run on the machine of Windows 2000, etc., ie no need. Support for .NET Framework.
3.1.2 Message Queue Technology
The MSMQ (Microsoft Message Queue Server, Microsoft Message Queue Server, Microsoft Message Quele Server) provided by Microsoft can also achieve the focus of this article, which is not described here.
Note: MSMQ is only available in the operating system after Windows 2000, and does not act as a systematic installation, you need to increase after installing the system.
3.2 Loose coupling events (Loosely Coupled Events, LCE)
3.2.1 Event Drive of Com
Although the event driver in CoM can be achieved by connecting point technology, it has some shortcomings:
n Publishers and subscriber life cycles are closely related, not suitable for enterprise applications
n The connection point requires multiple interactions in establishing and disconnecting, the efficiency is low, there is a problem with distributed applications.
N TCE does not have an event filtering mechanism
For these problems, a mechanism for publishing and subscribing to the LCE event is introduced in COM , called COM Event (COM EVENT). It has a lot of good characteristics, this article cannot be introduced more detailed in COM , here is only the implementation of COM Event, and advanced options such as event filtering, security settings, please refer to COM related books.
Example Description: Design a stock price release and subscription system. When the stock price changes, the publisher automatically notifies the subscriber (call the subscriber's method) implementation step:
1, write event components
N Create a COM component engineering from ATL COM Wizard Xevent
n Create components through ATL Object Wizard, no need to set Support Connection Points in Attributes
N to IStockevent increase how to get quote
HRESULT Newquote ([in] bstr bssymbol, [in] double DVALUE;
There is no need to implement the method, you can only return S_OK.
n compiled, registration
2, install event components (take Windows 2000 Professional as an Example)
n Open Component Services under "Control Panel" ==> "Administrative Tools"
N Right-click on the COM application, "New" ==> Applications, create an Application for the event component, named stockappappa
n On the component menu under the new STOCKAPP application, right-click, "New" ==> "Components"
n Select "Install new event classes"
n Import the event components written in the first step, the wizard will automatically discover the components and the interfaces in the component.
N installation completed
3. Write an event subscription service
N New COM component items in ATL COM AppWizard, named StocksUbscriber
n Import Event Component Interface
Add in stdafx.h
#import "../test.tlb" Raw_Interfaces_only no_namespace, named_guids
n Add to file Xevent.h in the project
n Create a new Simple Object with ATL Object Wizard, named StockeventSubscriber, this step is just to let ATL will automatically generate IDL files and COCLASS C class packages, so interface iStockeventSubscriber is nothing to do, you can delete it (How to delete it below), of course, you can write IDL and CstockeventSubscriber without passing ATL Object Wizard.
n Modify CoClass in StockeventSubscriber.idl to make it the default interface for iStockevent
Modify the Library section:
Library stocksubscriberlib
{
Importlib ("stdole32.tlb");
Importlib ("stdole2.tlb");
Importlib ("../ Xevent / Xevent.tlb");
[
UUID (e
04C
02F
3-F8B4
-489C
-B
91F
-A04D3DB5AEFD,
Helpstring ("Stockeventsubscriber Class")
]
CoClass Stockeventsubscriber
{
[Default] interface istockevent;
Interface iStockeventsubscriber;
}
}
n To increase the implementation of iStockevent (i.e., when triggering events will be executed) header files,
...
Class ATL_NO_VTABLE CSTOCKEVENTSUBSCRIBER:
Public CComobjectrootex
Public CCOMCOCLASS
Public IDispatchImpl
Public IDispatchImpl
...
Begin_COM_MAP (CstockeventSubscriber)
COM_ITERFACE_ENTRY (IStockeventsubscriber)
COM_ISTERFACE_ENTRY (ISTOCKEVENT)
Com_interface_entry2 (iDispatch, iStockevent)
END_COM_MAP ()
...
// iStockevent
PUBLIC:
STDMETHOD (NEWQUOTE) (BSTR Bssymbol, Double Dvalue);
...
Implement files stockeventsubscriber.cpp
...
StdMethodimp Cstockeventsubsbscribever :: Newquote (BSTR Bssymbol, Double Dvalue)
{
TCHAR BUF [100];
_stprintf (buf, _t ("% s% lf"), bssymbol, dvalue;
:: MessageBox (NULL, BUF, _T ("stock price"), MB_OK;
Return S_OK;
}
n compiled, registration
n Attached: The above steps actually produced a "empty" interface ISTOCKEVENTSUBSCRIBER without any purposes, and gives a step to remove it
n In the stockeventsubscriber.idl file, delete the interface definition
[
Object,
UUID (1FBF
1C
53-35B5-4E59-B821-AE68D16E4536),
Dual,
Helpstring ("iStockeventsubscriber Interface),
Pointer_DEFAULT (UNIQUE)
]
Interface iStockeventsubscriber: idispatch
{
}
Delete Interface Description in CoClass
Interface iStockeventsubscriber;
n In the stockeventsubscriber.h header file, delete the implementation of the IStockeventsubscriber interface
Public IDispatchImpl
...
COM_ITERFACE_ENTRY (IStockeventsubscriber)
Modify COM_ITERFACE_ENTRY2 (iDispatch, iStockevent) for com_interface_entry (iDispatch)
n compiled, registration
4, install event subscription service
N New component under the component of "Component Service" ==> "stockapp", select "Install the new component", install stocksubscriber.dll
5, subscription service
N in "Component Services" ==> "stockapp" component ==> "Stocksubscriber.Stockeventsubscriber, STOCKEVENTSBSCRIBER
.1
"
==> "Subscribe" right button, "New" ==> "Subscribe"
n Select the subscription method, select iStockevent, click "Next"
n Select event class, select an event class, point "Next"
n Subscription Options, to subscribe to a name stocksubscriber, select "Enable the subscription now", click "Next"
N completed subscription
5, test event driver
We write a simple COM component call with VB (exactly the same as VC written), and call the Xevent's NewStock () method, it will find that the Newstock method in the stocksubscriber is also called (pop-up dialog), proof The event was properly subscribed.
code show as below:
Private submmand1_click ()
Set stockpriceevent = creteObject ("xevent.stockevent")
StockPriceEvent.newquote "test", 100
End Sub
6, make COM installation files
The COM component service automatically provides features that package distribution to component, right-click "component service" ==> "stockapp", "Export"
You can then automatically generate the installation file, you can install directly on other machines in the future, COM components can be properly installed.
other instructions:
n Many of the COM can also achieve many of the other features of COM , such as JIT, object pool, security features, etc.
N COM is at least to use the machine above Windows 2000.
4. Summary
Implementing the event driver of COM includes TCE and LCE two modes, TCE can be implemented by the Connection Point or message queue, and the LCE is implemented through the COM subscriber model.
Realize the connection point: VC7 is simpler, more fully, more stable, and VC6.0's ATL is often easy to have some small problems.
COM Subscriber Model: COM can provide better operating characteristics, as well as more flexible configuration management, but can only run in Windows 2,000.
Select an implementation based on the specific situation when implementing the event drive.
Download PDF version