Template Callbacks
ClanLib includes a complete signalling library -- a signal library is a C++ template library that allow you to use type-safe C++ templates to setup function callbacks.
The library currently supports three different types of callback templates:
- Signals and slots
- Virtual functions
- Callbacks
Signals and Slots
A signal is an object that, when emitted, invokes one or more slot functions. This setup allows a one-way messaging system that informs a number of functions whenever a certain event occours. A simple example with one signal and two slot functions:
void slot_function1(int p1, int p2) { CL_Console::write_line("Slot 1: %1,%2", p1, p2); } void slot_function2(int p1, int p2) { CL_Console::write_line("Slot 2: %1,%2", p1, p2); } // Create signal and hook up slots: CL_Signal_v2<int, int> signal; CL_Slot slot1 = signal.connect(&slot_function1); CL_Slot slot2 = signal.connect(&slot_function2); // Emit signal: signal.invoke(21, 42);
The 'v2' part of CL_Signal_v2 indicates that the slot functions returns void and take 2 parameters. The types of the parameters are then defined as int, int. When the CL_Slot handle object returned by CL_Signal_vX::connect is destroyed, the slot function is disconnected from the signal. If you plan to connect a lot of slots to signals, the CL_SlotContainer class may come in handy:
void slot_function1(int p1, int p2, CL_String p3); void slot_function2(int p1, int p2, CL_String p3); CL_SlotContainer slots; CL_Signal_v3<int, int, CL_String> signal; slots.connect(signal, &slot_function1); slots.connect(signal, &slot_function2); signal.invoke(21, 42, "text");
Just like with the CL_Thread::start and cl_format functions, the slot callback function can be placed in a class and have additional fixed parameters passed along:
class MyClass { public: void slot_func(int p1, int p2, int user1); CL_SlotContainer slots; }; CL_Signal_v2<int, int> signal; MyClass my_class; my_class.slots.connect(signal, &my_class, &MyClass:slot_func, 100); my_class.slots.connect(signal, &my_class, &MyClass:slot_func, 200); signal.invoke(21, 42);
Virtual Functions
The CL_VirtualFunction_X template classes offers a different type of signal object, where each function connected replaces the previous object:
int slot_function1(int p1, int p2) { return p1 + p2; } int slot_function2(int p1, int p2, CL_Super_2<int, int, int> &super) { if (super.is_invokable()) return -super.invoke(p1, p2); else return 0; } // Create signal and hook up slots: CL_VirtualFunction_3<int, int, int> signal; CL_Slot slot1 = signal.connect(&slot_function1); CL_Slot slot2 = signal.connect(&slot_function2); // Emit signal: int result = signal.invoke(21, 42); // result becomes -(p1 + p2)
In this example the CL_VirtualFunction::invoke function calls slot_function2, which then calls slot_function2 - just like a virtual function in a derived class could do.
Callbacks
The last type of callback template classes available is CL_Callback_X. It simply calls one callback function when invoked, just like a standard C style function pointer would do.
int callback_function(int p1, int p2) { return p1 + p2; } CL_Callback_2<int, int, int> callback; callback.set(&callback_function); int result = callback.invoke(21, 42);