What Is the Proper Way of Doing Event Handling in C++

What is the proper way of doing event handling in C++?

The C++ Standard doesn't address events at all. Usually, however, if you need events you are working within a framework that provides them (SDL, Windows, Qt, GNOME, etc.) and ways to wait for, dispatch and use them.

Aside from that, you may want to look at Boost.Signals2.

Event driven design in c

I would assume you're owning an embedded system with access to interrupts or a major event loop in a separate thread, otherwise this isn't possible..

A basic model for event handling is here:

#define NOEVENT 0

typedef void *(*EventHandler)(void *);

void *doNothing(void *p){/*do nothing absolutely*/ return NULL; }
typedef struct _event{
EventHandler handler;
}Event, *PEvent;

Event AllEvents[1000];
unsigned short counter = 0;
void InitEvents()
{
LOCK(AllEvents);
for(int i = 0; i < 1000; i++){
AllEvents[i].handler = doNothing;
}
UNLOCK(AllEvents);
}
void AddEvent(int EventType, EventHandler ev_handler)
{
LOCK(AllEvents);
AllEvents[EventType].handler = ev_handler;
UNLOCK(AllEvents);
}

void RemoveEvent(int EventType, EventHandler ev_handler)
{
LOCK(AllEvents);
AllEvents[EventType] = doNothing;
UNLOCK(AllEvents); /*to safeguard the event loop*/
}

/*to be run in separate thread*/
void EventLoop()
{
int event = NOEVENT;
EventHandler handler;
while(1){
while(event == NOEVENT)event=GetEvents();
handler = AllEvents[event].handler;
handler();/*perform on an event*/
}
}

C++ Event Handling

Use std::function as a callback:

void printSomething() { std::cout << "event!" << std::endl; }

int main() {
std::function<void()> onEvent;
onEvent = &printSomething;
onEvent(); // prints "event!"
}

If you want C#-style delegates, use std::vector<std::function<...>>:

struct Delegate {
std::vector<std::function<void()>> funcs;
template<class T> Delegate& operator+=(T mFunc) { funcs.push_back(mFunc); return *this; }
void operator()() { for(auto& f : funcs) f(); }
};

int main() {
Delegate delegate;
delegate += []{ std::cout << "hello, "; };
delegate += []{ std::cout << "world!" << endl; };
delegate(); // prints "hello, world!"
}

Or just copy my ssvu::Delegate class, available here.

What is the preferred method for event handling in C#?

The first way is what Microsoft suggests. The pattern is:

  1. some code wants to raise an event, calls OnXxx
  2. OnXxx makes a call to the delegate
  3. Wired event handlers are called

If you perform the second model, you risk forgetting the base.OnXxx call and breaking everything. Nice part of option 2 is that you get to decide if you are called before or after all of the other event handlers. If you put your code before the base.OnXxx, you get executed before the event does. Of course the first model can be used always, the second only if you are subclassing the class raising the event.

How to handle an event in Windows C++

Event handler is an abstract concept that exists somehow is all general purpose programming languages.

C++ is no exception.
For C++ under windows you can define a custom event, a source that will raise this event, and a receiver or an event listener/handler.

Check the sample code here

https://msdn.microsoft.com/en-us/library/ee2k0a7d.aspx

Understanding events and event handlers in C#

To understand event handlers, you need to understand delegates. In C#, you can think of a delegate as a pointer (or a reference) to a method. This is useful because the pointer can be passed around as a value.

The central concept of a delegate is its signature, or shape. That is (1) the return type and (2) the input arguments. For example, if we create a delegate void MyDelegate(object sender, EventArgs e), it can only point to methods which return void, and take an object and EventArgs. Kind of like a square hole and a square peg. So we say these methods have the same signature, or shape, as the delegate.

So knowing how to create a reference to a method, let's think about the purpose of events: we want to cause some code to be executed when something happens elsewhere in the system - or "handle the event". To do this, we create specific methods for the code we want to be executed. The glue between the event and the methods to be executed are the delegates. The event must internally store a "list" of pointers to the methods to call when the event is raised.* Of course, to be able to call a method, we need to know what arguments to pass to it! We use the delegate as the "contract" between the event and all the specific methods that will be called.

So the default EventHandler (and many like it) represents a specific shape of method (again, void/object-EventArgs). When you declare an event, you are saying which shape of method (EventHandler) that event will invoke, by specifying a delegate:

//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyEventHandler(string foo);

//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyEventHandler SomethingHappened;

//Here is some code I want to be executed
//when SomethingHappened fires.
void HandleSomethingHappened(string foo)
{
//Do some stuff
}

//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);

//To raise the event within a method.
SomethingHappened("bar");

(*This is the key to events in .NET and peels away the "magic" - an event is really, under the covers, just a list of methods of the same "shape". The list is stored where the event lives. When the event is "raised", it's really just "go through this list of methods and call each one, using these values as the parameters". Assigning an event handler is just a prettier, easier way of adding your method to this list of methods to be called).

Event handling using SDL and C for my hobby game engine

If you want end-users to write the functions for handling the events, I would suggest relying on callbacks. The idea is that the end-user will dictate what event handler to call for each event type, whereas the game engine will dictate when to call the corresponding event handler.

The user is provided with a struct of callbacks so that user code can define custom event handlers and configure these callbacks to refer to these custom functions. Then, the loop for event processing of the game engine calls those functions via the callbacks set up by the user.


Example

You could define different function types for different events:

typedef void (*quit_handler_t)(void);
typedef void (*keydown_handler_t)(SDL_Keycode);
typedef void (*keyup_handler_t)(SDL_Keycode);

That is, the handler for quitting takes no arguments, whereas those for a key going up and down takes an argument that represents the corresponding key.

Then, you provide the client with a struct, event_handlers, that contains pointers to the event handlers and the end-user is supposed to populate:

struct {
quit_handler_t quit;
keydown_handler_t keydown;
keyup_handler_t keyup;
} event_handlers;

Finally, the game engine's loop for processing the events call those functions through the callbacks that were set up by the user:

SDL_Event e;
while (!quit && SDL_PollEvent(&e)) {
switch(e.type) {
case SDL_QUIT:
event_handlers.quit();
break;
case SDL_KEYDOWN:
event_handlers.keydown(e.key.keysym.sym);
break;
case SDL_KEYUP:
event_handlers.keyup(e.key.keysum.sym);
break;
}
}

Note that the game engine could also initialize the event_handler struct with default event handlers. The end-user would be able to override that default behavior by modifying the members of event_handler.



Related Topics



Leave a reply



Submit