ClanLib SDK

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

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);