< Old To New C++ .Net version 6 | Main | Old To New C++ .Net version 8 >


 

 

Early Stages of the C++ .Net 29

(From Managed Extensions for C++ to new C++ .NET Syntax)

 

 

 

 

 

The code snippets used in this module if any are Visual C++ .Net 2003 dominated and if compiled using Visual C++ .Net 2005 you need to use the /clr:oldSyntax option). The following are the topics available in this module.

  1. The __hook Keyword

  2. The __unhook Keyword

  3. The __raise Keyword

 

 

The __hook Keyword

 

The __hook keyword associates a handler method with an event.

long __hook(&SourceClass::EventMethod,source,

&ReceiverClass::HandlerMethod[, receiver = this]);

 

long __hook(

      interface,

      source

);

 

 

Parameters

Description

&SourceClass::EventMethod

A pointer to the event method to which you hook the event handler method:

  1. Native C++ events: SourceClass is the event source class and EventMethod is the event.

  2. COM events: SourceClass is the event source interface and EventMethod is one of its methods.

  3. Managed events: SourceClass is the event source class and EventMethod is the event.

interface

The interface name being hooked to receiver, only for COM event receivers in which the layout_dependent parameter of the event_receiver attribute is true.

source

A pointer to an instance of the event source. Depending on the code type specified in event_receiver, source can be one of the following:

  1. A native event source object pointer.

  2. An IUnknown-based pointer (COM source).

  3. A managed object pointer (for managed events).

&ReceiverClass::HandlerMethod

A pointer to the event handler method to be hooked to an event. The handler is specified as a method of a class or a reference to the same; if you do not specify the class name, __hook assumes the class to be that in which it is called.

  1. Native C++ events: ReceiverClass is the event receiver class and HandlerMethod is the handler.

  2. COM events: ReceiverClass is the event receiver interface and HandlerMethod is one of its handlers.

  3. Managed events: ReceiverClass is the event receiver class and HandlerMethod is the handler.

receiver (optional)

A pointer to an instance of the event receiver class. If you do not specify a receiver, the default is the receiver class or structure in which __hook is called.

 

Table 7

 

__hook can be use in any function scope, including main, outside the event receiver class. Use the intrinsic function __hook in an event receiver to associate or hook a handler method with an event method. The specified handler is then called when the source raises the specified event. You can hook several handlers to a single event or hook several events to a single handler. There are two forms of __hook:

 

  1. You can use the first (four-argument) form in most cases, specifically, for COM event receivers in which the layout_dependent parameter of the event_receiver attribute is false. In these cases you do not need to hook all methods in an interface before firing an event on one of the methods; only the method handling the event needs to be hooked.

  2. You can use the second (two-argument) form of __hook only for a COM event receiver in which layout_dependent = true.

 

__hook returns a long value. A nonzero return value indicates that an error has occurred (managed events throw an exception). The compiler checks for the existence of an event and that the event signature agrees with the delegate signature. With the exception of COM events, __hook and __unhook can be called outside the event receiver. An alternative to using __hook is to use the += operator. The following example shows how to fire an event in native C++.

// Test.cpp : main project file.

// __hook keyword, event handling in native C++ example

// compile with: /clr

#include "stdafx.h"

#include <stdio.h>

 

using namespace System;

 

[event_source(native)]

class CSource

{

      public:

            __event void MyEvent(int nValue);

};

 

[event_receiver(native)]

class CReceiver

{

      public:

            void MyHandler1(int nValue)

            {

                  printf_s("MyHandler1 was called with value %d.\n", nValue);

            }

 

            void MyHandler2(int nValue)

            {

                  printf_s("MyHandler2 was called with value %d.\n", nValue);

            }

 

            void hookEvent(CSource* pSource)

            {

                  __hook(&CSource::MyEvent, pSource, &CReceiver::MyHandler1);

                  __hook(&CSource::MyEvent, pSource, &CReceiver::MyHandler2);

            }

 

            void unhookEvent(CSource* pSource)

            {

                  __unhook(&CSource::MyEvent, pSource, &CReceiver::MyHandler1);

                  __unhook(&CSource::MyEvent, pSource, &CReceiver::MyHandler2);

            }

};

 

int main()

{

      CSource source;

      CReceiver receiver;

 

      receiver.hookEvent(&source);

      __raise source.MyEvent(1234);

      receiver.unhookEvent(&source);

}

 

Output:

 __hook, __raise keywords program output .NET event handling

 

The __unhook Keyword

 

The __unhook keyword dissociates a handler method from an event.

long  __unhook(

   &SourceClass::EventMethod,

      source,

   &ReceiverClass::HandlerMethod

   [, receiver = this]

);

long  __unhook(

      interface,

      source

);

long  __unhook(

      source

);

 

Parameters

Description

&SourceClass::EventMethod

A pointer to the event method from which you unhook the event handler method:

  1. Native C++ events: SourceClass is the event source class and EventMethod is the event.

  2. COM events: SourceClass is the event source interface and EventMethod is one of its methods.

  3. Managed events: SourceClass is the event source class and EventMethod is the event.

interface

The interface name being unhooked from receiver, only for COM event receivers in which the layout_dependent parameter of the event_receiver attribute is true.

source

A pointer to an instance of the event source. Depending on the code type specified in event_receiver, source can be one of the following:

  1. A native event source object pointer.

  2. An IUnknown-based pointer (COM source).

  3. A managed object pointer (for managed events).

&ReceiverClass::HandlerMethod

A pointer to the event handler method to be unhooked from an event. The handler is specified as a method of a class or a reference to the same; if you do not specify the class name, __unhook assumes the class to be that in which it is called.

  1. Native C++ events: ReceiverClass is the event receiver class and HandlerMethod is the handler.

  2. COM events: ReceiverClass is the event receiver interface and HandlerMethod is one of its handlers.

  3. Managed events: ReceiverClass is the event receiver class and HandlerMethod is the handler.

receiver (optional)

A pointer to an instance of the event receiver class. If you do not specify a receiver, the default is the receiver class or structure in which __unhook is called.

 

Table 8

 

__unhook can be use in any function scope, including main, outside the event receiver class. Use the intrinsic function __unhook in an event receiver to dissociate or "unhook" a handler method from an event method. There are three forms of __unhook:

 

  1. You can use the first (four-argument) form in most cases.

  2. You can use the second (two-argument) form of __unhook only for a COM event receiver; this unhooks the entire event interface.

  3. You can use the third (one-argument) form to unhook all delegates from the specified source.

 

A nonzero return value indicates that an error has occurred (managed events will throw an exception). If you call __unhook on an event and event handler that are not already hooked, it will have no effect. At compile time, the compiler verifies that the event exists and does parameter type checking with the specified handler. With the exception of COM events, __hook and __unhook can be called outside the event receiver. An alternative to using __unhook is to use the -= operator.

 

The __raise Keyword

 

The __raise keyword emphasizes the call site of an event. The syntax is:

__raise method-declarator;

 

From managed code, an event can only be raised from within the class where it is defined. The keyword __raise causes an error to be emitted if you call a non-event as shown in the following example.

// Test.cpp : main project file.

// Event Handling, raise keyword

// compile with: /clr

#include "stdafx.h"

 

using namespace System;

 

struct myE

{

      __event void func1();

      void func1(int) {}

      void func2() {}

      void myb()

      {

            __raise func1();

            // Expect C3745 error: 'int Event::bar(int)': only an event can be 'raised'

            __raise func1(1);

            __raise func2();   // Expect C3745 error

      }

};

 

int main()

{

      myE mye;

      __raise mye.func1();

      __raise mye.func1(1);  // Expect C3745 error

      __raise mye.func2();   // Expect C3745 error

     

      return 0;

}

The following is the sample output seen from the Visual C++ IDE's Output window.

1>------ Build started: Project: Test, Configuration: Debug Win32 ------

1>Compiling...

1>Test.cpp

1>.\Test.cpp(20) : error C3745: 'void myE::func1(int)': only an event can be 'raised'

1>.\Test.cpp(21) : error C3745: 'void myE::func2(void)': only an event can be 'raised'

1>.\Test.cpp(29) : error C3745: 'void myE::func1(int)': only an event can be 'raised'

1>.\Test.cpp(30) : error C3745: 'void myE::func2(void)': only an event can be 'raised'

1>Build log was saved at "file://f:\vc2005project\Test\Test\Debug\BuildLog.htm"

1>Test - 4 error(s), 0 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

 

Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7 | Part 8 | Part 9

 


 

< Old To New C++ .Net version 6 | Main | Old To New C++ .Net version 8 >