]> git.lyx.org Git - lyx.git/blob - sigc++/doc/signals
fix typo that put too many include paths for most people
[lyx.git] / sigc++ / doc / signals
1
2 1.0 Signals
3 ==============
4
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. 
19  
20 1.1 How does the communication work?
21 ------------------------------------
22
23 In the callback mechanism there's 3 separate entities involved. 
24
25      sender 
26      receiver 
27      someone making connection between sender and receiver 
28
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". 
33
34 The receiver of the signal can be almost anything.  In Libsigc++ the 
35 following objects can receive messages: 
36
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 
42
43 All connections share a common syntax through a factory that creates a
44 abstract function object called a "Slot."
45
46
47      signal.connect(slot(object,Object::&method));
48      signal.connect(slot(&function));
49      signal.connect(functionobject.slot())
50
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 
57 type error. 
58
59
60
61 2.0 Implementation of signals
62 =============================
63
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: 
67
68   Signal2<void, int, float> buttonPressed;
69
70   where
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
75
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:
79
80   void my_function(int param1, float param2);
81   buttonPressed.connect(slot(&my_function));
82
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: 
85
86   MyClass myobject; 
87   buttonPressed.connect(slot(myobject,&MyClass::my_function));
88
89 If the signal is inside an object, you'll need to specify it too: 
90
91   obj.buttonPressed.connect(slot(myobject, &MyClass::my_function));
92
93
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.
98
99 Calling a signal looks exactly like calling normal C++ function: 
100
101   buttonPressed(10, 20.0);
102
103 or in case where you have the signal inside an object, call is in format: 
104
105   obj.buttonPressed(10, 20.0);
106
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.
110
111   obj.buttonPressed.emit(10, 20.0);
112
113
114
115 2.1 Signals with return types
116 ------------------------------
117
118 All signals have a return type which may be void.  
119
120   Signal1<int,int> signal;
121
122 That signal can be connected to the methods with the following signature:
123
124   int my_callback(int);
125
126 There are a few restrictions on the types of returns.  Return
127 types must have:
128
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);
132
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.
137
138 This means that the return type must not be a reference itself.  
139
140
141
142 2.2 Connecting to a signals 
143 -----------------------------
144
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: 
148
149 struct My_Button 
150   {
151    Signal0<void> clicked;
152   } b1,b2;
153
154 b1.clicked.connect(b2.clicked.slot());
155
156
157 2.3 Summery
158 ------------
159
160 Here is the summery of the properties of a signal
161
162 class Signal<Rettype,Args>
163   {
164    public:
165       Connection connect(const Slot<Rettype Args>&);
166       Slot<Rettype,Args> slot();
167       Rettype emit(Args);
168       Rettype operator()(Args);
169   };
170
171 Where:
172   Rettype is the return type of the signal.
173   Args are the arguments taken.
174
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.
178  
179
180 3.0 Common errors in use of the signals
181 =======================================
182
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)
186
187  * Signature of function does not match signal 
188      Return type? 
189      arguments have correct type? 
190      the signal has correct types?
191
192    Example error session:
193      void foo(int i);
194      Signal1<int,int> sig;
195      sig.connect(slot(foo));
196    
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> *)'
200                                          ^^^^^^^^^^^^^^^^
201                                        Signiture of function
202      >>signal.h: candidates are: 
203           Signal1<int,int>::connect<int, int> (Slot1<int,int> *)
204                                               ^^^^^^^^^^^^^^
205                                            Signiture of Signal
206  
207  * Using a reference as a return type
208
209    Example error session:
210      Signal1<int&,int> sig;
211
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
216
217   
218
219  * Connecting object is not derived from SigC::Object
220      
221    Example error session:
222      struct A {int foo(int);} a;
223      Signal1<int,int> sig;
224
225      sig.connect(slot(a,&A::foo));
226
227      foobar.cc:58: conversion from `A' to non-scalar type `Object' requested
228     
229    
230  * Forgot to name the connected function as a method.
231   
232    Example error session: 
233      struct A:public SigC::Object {int foo(int);} a;
234      Signal1<int,int> sig;
235
236      sig.connect(slot(a,foo));  // should be sig.connect(slot(a,&A::foo));
237
238      >>foobar.cc:47: no matching function for call to `slot (A &, int ()(int))'
239
240
241  * Forgot to use address of method on connection 
242    
243    Example error session:
244      struct A:public SigC::Object {int foo(int);} a;
245      Signal1<int,int> sig;
246
247      sig.connect(slot(a,A::foo)); // should be sig.connect(slot(a,&A::foo));
248
249      >> foobar.cc:23: warning: assuming & on `A::foo1(int)'
250   
251  
252  * Passed a pointer as object (**This is different from Gtk--**)
253     
254    Example error session:
255      struct A:public SigC::Object {int foo(int);} a;
256      Signal1<int,int> sig;
257
258      sig.connect(slot(&a,&A::foo)); // should be sig.connect(slot(a,&A::foo));
259
260      >>foobar.cc:93: conversion from `A *' to non-scalar type `Object' 
261        requested
262      >>object_slot.h:177: in passing argument 1 of 
263        `slot<A, int, int>(Object &, int (A::*)(int))'
264
265
266 4.0 Connections
267 ===============
268
269 4.1 Disconnecting signals
270 -------------------------
271
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(). 
275
276 Connection c;
277 c=o.buttonPressed.connect(slot(&myfunction));
278 ...
279 c.disconnect();
280
281 Its perfectly legal to just ignore the return value of connect() functions - 
282 all bookeeping information used by signal system is released properly.
283
284
285 5.0 Adaptors
286 ============
287
288 Often it is desirable to connect to a function and a signal
289 in which the signal and function signatures are not
290 exactly the same.
291
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 
294 type.  
295
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:
300
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
304
305   Examples:
306
307     int func(float);
308     Signal1<void,float> sig1;
309     Signal1<int> sig2;
310
311     // cover up float argument 
312     sig2.connect(bind(slot(&func),20.0f));    
313    
314
315