Here's code for an event system I made in C. Since it is programmed using macros it does not have to throw type safety away.
Events are defined by for example "evt_define(foobar2, int, float, int)". This can be used anywhere where declaring a variable is legal, such as within a struct. evt_typedef can also be used to capture the otherwise anonymous type.
The first type argument is the data that will be bound together with the handler function, and the rest are the types of the arguments that are provided when signaling the event.
The ##__VA_ARGS__ construct which will eat the leading comma when no arguments are provided is non-standard, but works in MSVC and GCC at least.
#include <stdio.h>#include <stdlib.h>// replace //\ with \#define evt_define(Name, DataType, ...) //\ struct { //\ short num, max; //\ union { //\ struct { //\ void (*func)(DataType, ##__VA_ARGS__); //\ DataType data; //\ } *binds; //\ void *untyped; //\ }; //\ } Name#define evt_typedef(Type, DataType, ...) //\ typedef evt_define(Type, DataType, ##__VA_ARGS__)#define evt_signal(Evt, ...) //\ do { //\ int i; //\ for(i = 0; i < (Evt).num; ++i) //\ (Evt).binds.func((Evt).binds.data, ##__VA_ARGS__); //\ } while(0)#define evt_bind(Evt, Func, Data) //\ do { //\ int num = (Evt).num; //\ int max = (Evt).max; //\ if(num == max) { //\ if(max) max *= 2; //\ else max = 2; //\ (Evt).untyped = realloc((Evt).binds, sizeof(*(Evt).binds) * max);//\ (Evt).max = max; //\ } //\ (Evt).binds[num].func = Func; //\ (Evt).binds[num].data = Data; //\ ++(Evt).num; //\ } while(0)#define evt_unbind(Evt, Func, Data) //\ do { //\ int i; //\ for(i = 0; i < (Evt).num; ++i) { //\ if((Func) == (Evt).binds.func && //\ (Data) == (Evt).binds.data) { //\ for((Evt).num -= 1; i < (Evt).num; ++i) { //\ (Evt).binds.func = (Evt).binds[i+1].func; //\ (Evt).binds.data = (Evt).binds[i+1].data; //\ } //\ break; //\ } //\ } //\ } while(0)static void on_foobar(int data, float f, int i) { printf("on_foobar %d\nargs: %f %d\n\n", data, f, i);}evt_typedef(FoobarEvent, int, float, int);int main(int argc, char *argv[]) { FoobarEvent foobar1 = {0,}; evt_define(foobar2, int, float, int) = {0,}; int data1 = 10; int data2 = 20; int data3 = 30; evt_bind(foobar1, on_foobar, data1); evt_bind(foobar1, on_foobar, data2); evt_bind(foobar2, on_foobar, data3); evt_signal(foobar1, 3.141f, 123); evt_signal(foobar2, 2.718f, 666); return 0;}
[Edited by - robinei on July 30, 2009 4:16:47 AM]