5 Signals are used for communication between objects. Rather
6 that using messy pointers or pointers to member functions to implement
7 callbacks this library provides an elegant connection framework for
8 connecting between static functions, member functions and function objects.
9 To add to this all types of connections can be made with compile time
10 type checking through an extensable template set. Unlike other solutions
11 that break the C++ language and add incompatible extensions or code
12 generation, Libsigc++ uses only the standard C++ definitions. Thus it
13 will not decrease the ability of tools designed to parse the C++ language
14 to handle your code. Libsigc++ provides signal framework which solves
15 your problems with communication between objects. This signal framework
16 makes your objects reusable components which are independent of other
17 objects it communicates with. This means reducing coupling between
18 objects and resulting less dependencies and thus more reusable code.
20 1.1 How does the communication work?
21 ------------------------------------
23 In the callback mechanism there's 3 separate entities involved.
27 someone making connection between sender and receiver
29 In actual code, the sender specifies an interface which it can call when
30 it wants to tell other objects something. This interface is specified as
31 a function object and is called "Signal". Calling that interface is
32 called "emitting a signal".
34 The receiver of the signal can be almost anything. In Libsigc++ the
35 following objects can receive messages:
37 member function of any object derived from SigC::Object
38 function object derived from SigC::Object
39 static, global or friend function
40 static function object
41 member function to a static object
43 All connections share a common syntax through a factory that creates a
44 abstract function object called a "Slot."
47 signal.connect(slot(object,Object::&method));
48 signal.connect(slot(&function));
49 signal.connect(functionobject.slot())
51 Making a connection connects sender to the receiver. After that, if the
52 sender emits a signal, all methods, functions and function objects that
53 have been connected to that signal are called with the arguments given at
54 signal emission. Signature of both sender interface and receiver method
55 must match exactly to be able to make connection between them. If there's
56 type mismatches in the signatures, C++ compiler will give compile time
61 2.0 Implementation of signals
62 =============================
64 Signals are C++ function objects. Because signals are normal C++-objects,
65 you can use them in file scope, in function local scope - but they're
66 most used inside class scope. A signal definition is of form:
68 Signal2<void, int, float> buttonPressed;
71 2 = number of arguments
72 void = type of the return
73 int = type of the first parameter of the signal
74 float = type of the 2nd parameter of the signal
76 This way application programmers can specify interface for a signal.
77 A connection from a signal to a (member) function matching signal's
78 interface can be made:
80 void my_function(int param1, float param2);
81 buttonPressed.connect(slot(&my_function));
83 If the function is a member function, you'll need to specify the object
84 too. Note that this object's class needs to be derived from Signal:
87 buttonPressed.connect(slot(myobject,&MyClass::my_function));
89 If the signal is inside an object, you'll need to specify it too:
91 obj.buttonPressed.connect(slot(myobject, &MyClass::my_function));
94 When connection between a signal and a function has been made, calling
95 the signal will make the system call all the connected functions with
96 given parameters. Of course many connections can be made to same signal
97 and the system will call all of them when the signal is called.
99 Calling a signal looks exactly like calling normal C++ function:
101 buttonPressed(10, 20.0);
103 or in case where you have the signal inside an object, call is in format:
105 obj.buttonPressed(10, 20.0);
107 An alternative method with a function name is also provided with
108 a method emit. This is to make it easier to distiguish and provides
109 a method name for STL connection calls.
111 obj.buttonPressed.emit(10, 20.0);
115 2.1 Signals with return types
116 ------------------------------
118 All signals have a return type which may be void.
120 Signal1<int,int> signal;
122 That signal can be connected to the methods with the following signature:
124 int my_callback(int);
126 There are a few restrictions on the types of returns. Return
129 a default constructor T t;
130 a copy constructor T t1,t2; t1=t2;
131 a reference form T t1; void func(T& t); func(t1);
133 A default ctor is required so that a temporary object can be
134 created to hold the return type. A copy constructor is required
135 so that the signal can be marshalled. A reference form is required
136 to pass the return types to the marshaller functions.
138 This means that the return type must not be a reference itself.
142 2.2 Connecting to a signals
143 -----------------------------
145 Because Libsigc++ signals use function objects heavily, there needs to be
146 way to connect a signal to another signal. Lets connect a button's
147 clicked()-signal to another button's clicked signal:
151 Signal0<void> clicked;
154 b1.clicked.connect(b2.clicked.slot());
160 Here is the summery of the properties of a signal
162 class Signal<Rettype,Args>
165 Connection connect(const Slot<Rettype Args>&);
166 Slot<Rettype,Args> slot();
168 Rettype operator()(Args);
172 Rettype is the return type of the signal.
173 Args are the arguments taken.
175 connect() inserts a slot with the same profile into the signal.
176 slot() returns a slot for connecting this signal to another.
177 emit() calls all slots in the signal.
180 3.0 Common errors in use of the signals
181 =======================================
183 Here are some common errors and an example of some of the errors that
184 they generate. (Do not take this as an example of proper use!
185 Errors similified for clarity. Your compiler messages will differ)
187 * Signature of function does not match signal
189 arguments have correct type?
190 the signal has correct types?
192 Example error session:
194 Signal1<int,int> sig;
195 sig.connect(slot(foo));
197 >>foobar.cc: In function `int main()':
198 >>foobar.cc:17: no matching function for call to
199 `Signal1<int,int>::connect (Slot1<void,int> *)'
201 Signiture of function
202 >>signal.h: candidates are:
203 Signal1<int,int>::connect<int, int> (Slot1<int,int> *)
207 * Using a reference as a return type
209 Example error session:
210 Signal1<int&,int> sig;
212 >>basic_signal.h: In method `int & Signal1_<int &,int>::Impl::
213 emit<int &, int>(int)':
214 >>signal.h:100: instantiated from here
215 >>basic_signal.h:244: `rc' declared as reference but not initialized
219 * Connecting object is not derived from SigC::Object
221 Example error session:
222 struct A {int foo(int);} a;
223 Signal1<int,int> sig;
225 sig.connect(slot(a,&A::foo));
227 foobar.cc:58: conversion from `A' to non-scalar type `Object' requested
230 * Forgot to name the connected function as a method.
232 Example error session:
233 struct A:public SigC::Object {int foo(int);} a;
234 Signal1<int,int> sig;
236 sig.connect(slot(a,foo)); // should be sig.connect(slot(a,&A::foo));
238 >>foobar.cc:47: no matching function for call to `slot (A &, int ()(int))'
241 * Forgot to use address of method on connection
243 Example error session:
244 struct A:public SigC::Object {int foo(int);} a;
245 Signal1<int,int> sig;
247 sig.connect(slot(a,A::foo)); // should be sig.connect(slot(a,&A::foo));
249 >> foobar.cc:23: warning: assuming & on `A::foo1(int)'
252 * Passed a pointer as object (**This is different from Gtk--**)
254 Example error session:
255 struct A:public SigC::Object {int foo(int);} a;
256 Signal1<int,int> sig;
258 sig.connect(slot(&a,&A::foo)); // should be sig.connect(slot(a,&A::foo));
260 >>foobar.cc:93: conversion from `A *' to non-scalar type `Object'
262 >>object_slot.h:177: in passing argument 1 of
263 `slot<A, int, int>(Object &, int (A::*)(int))'
269 4.1 Disconnecting signals
270 -------------------------
272 Every signal.connect()-function returns a Connection object,
273 which can be stored and it can be used to disconnect the connection
274 by calling function disconnect().
277 c=o.buttonPressed.connect(slot(&myfunction));
281 Its perfectly legal to just ignore the return value of connect() functions -
282 all bookeeping information used by signal system is released properly.
288 Often it is desirable to connect to a function and a signal
289 in which the signal and function signatures are not
292 For example, it would be good to ignore the return type
293 of a function when placing it into a signal with a void return
296 Fortunately, Libsigc++ provides a mechanism to accomplish this
297 type of connection. There is a broad class of slot "Adaptors".
298 These functions take a slot of one type and produce a slot of
299 another. Here are some sample adaptors provided:
301 bind(Slot, v1) - Passes v1 as last argument to Slot
302 (The number of arguments is reduced for the resulting slot)
303 bind(Slot, v1, v2) - Passes v1 and v2 as last arguments to Slot
308 Signal1<void,float> sig1;
311 // cover up float argument
312 sig2.connect(bind(slot(&func),20.0f));