Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

sigslot.i 29.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/*
 * Module providing SWIG wrappers for sigslot that make it possible to use Lua functions as slots.
 *
 * SWIG's lua_fnptr extension and one of the structures it defines, SWIGLUA_REF, are used to handle
 * Lua functions on the C++ side.
 */

%module sigslot

%include lua_fnptr.i

%{
13
14
#include <cstdio>
#include <iostream>
15
#include "tbb/recursive_mutex.h"
16
#include "ext/cgt/logmanager.h"
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "ext/sigslot/sigslot.h"
%}


%inline {
namespace sigslot {

    /**
     * Signal arguments need to be wrapped before they can be passed to slots defined in Lua. That
     * requires the textual representation of their respective types to be known. Unfortunately,
     * there is no portable way to get a string describing a type in C++, and SWIG doesn't expose
     * such functionality. Consequently, we use a trait for that purpose; it needs to be specialised
     * for all types used as arguments of signals that are exposed to Lua, e.g.:
     *
     * template<>
     * struct LuaConnectionArgTraits<campvis::AbstractProcessor*> {
     *     static const char* const typeName;
     * };
     *
     * const char* const LuaConnectionArgTraits<campvis::AbstractProcessor*>::typeName = "campvis::AbstractProcessor *";
     */
    template<typename T>
    struct LuaConnectionArgTraits {};

    /*
     * Type bundling all information necessary to inject a signal argument into a Lua state:
     * a pointer to the argument and its corresponding SWIG type information.
     */
    typedef std::pair<void*, swig_type_info*> ArgWithTypeInfoType;

    /*
     * Return an object bundling the provided argument with its SWIG type information.
     */
    template<typename T>
    inline ArgWithTypeInfoType getArgWithTypeInfo(T arg) {
        const char* const typeName = LuaConnectionArgTraits<T>::typeName;
        swig_type_info* typeInfo = SWIG_TypeQuery(typeName);

        if (typeInfo == nullptr) {
56
            LogMgr.log("Lua", cgt::LuaError, "SWIG wrapper for " + std::string(typeName) + " not found");
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
        }

        return std::make_pair(arg, typeInfo);
    }

    /*
     * Prepend a new element to a list of objects that bundle arguments with their SWIG type
     * information and return the resulting list.
     */
    inline std::list<ArgWithTypeInfoType>* argWithTypeInfoListCons(ArgWithTypeInfoType head,
                                                                   std::list<ArgWithTypeInfoType>* tail)
    {
        if (head.second == nullptr) {
            delete tail;
        } else if (tail != nullptr) {
            tail->push_front(head);
            return tail;
        }

        return nullptr;
    }

    /*
     * Series of functions that take several arguments and return a list of objects that bundle
     * those arguments with their SWIG type information.
     */

    template<typename T>
    inline std::list<ArgWithTypeInfoType>* getArgWithTypeInfoList(T arg) {
        return argWithTypeInfoListCons(getArgWithTypeInfo<T>(arg), new std::list<ArgWithTypeInfoType>());
    }

    template<typename T1, typename T2>
    inline std::list<ArgWithTypeInfoType>* getArgWithTypeInfoList(T1 arg1, T2 arg2) {
        return argWithTypeInfoListCons(getArgWithTypeInfo<T1>(arg1), getArgWithTypeInfoList<T2>(arg2));
    }

    template<typename T1, typename T2, typename T3>
    inline std::list<ArgWithTypeInfoType>* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3) {
        return argWithTypeInfoListCons(getArgWithTypeInfo<T1>(arg1), getArgWithTypeInfoList<T2, T3>(arg2, arg3));
    }

    template<typename T1, typename T2, typename T3, typename T4>
    inline std::list<ArgWithTypeInfoType>* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
        return argWithTypeInfoListCons(getArgWithTypeInfo<T1>(arg1),
                                       getArgWithTypeInfoList<T2, T3, T4>(arg2, arg3, arg4));
    }

    template<typename T1, typename T2, typename T3, typename T4, typename T5>
    inline std::list<ArgWithTypeInfoType>* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
        return argWithTypeInfoListCons(getArgWithTypeInfo<T1>(arg1),
                                       getArgWithTypeInfoList<T2, T3, T4, T5>(arg2, arg3, arg4, arg5));
    }

    // Type of mutex used to guard access to Lua state. See LuaVmState for more details.
    typedef tbb::recursive_mutex LuaStateMutexType;

    /*
     * Base class for Lua connections for specific signal arities.
     *
     * This class implements the bridging between sigslot's signals and slots defined in Lua, as
     * well as some other logic (e.g. copySlotFunction and getDummyDest) common to all Lua
     * connections. Subclasses need simply to call the helpers provided by this class from their
     * interface implementation methods.
121
122
123
124
     *
     * The template parameter is just a dummy parameter to enforce that _connection_base0 is always
     * locally instantiated as template and not linked into the sigslot library. This makes writing
     * scripting bindings much easier
125
     */
126
    template<int DUMMY_PARAMETER = 0>
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    class _lua_connection_base {
    public:
        _lua_connection_base(SWIGLUA_REF slot_fn)
            : _slot_fn(slot_fn)
            , _dummy_dest(nullptr)
        {
            // Retrieve from the registry the mutex associated with the function's Lua state
            lua_pushlightuserdata(slot_fn.L, static_cast<void*>(slot_fn.L));
            lua_gettable(slot_fn.L, LUA_REGISTRYINDEX);

            // The mutex should be stored as light userdata
            assert(lua_islightuserdata(slot_fn.L, -1));
            _lua_state_mutex = static_cast<LuaStateMutexType*>(lua_touserdata(slot_fn.L, -1));
            lua_pop(slot_fn.L, 1);
        }

        _lua_connection_base(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex)
            : _slot_fn(slot_fn)
            , _dummy_dest(nullptr)
            , _lua_state_mutex(lua_state_mutex)
        {}

        virtual ~_lua_connection_base() {
            swiglua_ref_clear(&_slot_fn);

            if (_dummy_dest != nullptr)
                delete _dummy_dest;
        }

        /**
         * Check if this connection's slot function is the same as the given Lua function.
         *
         * @param slot_fn reference to a Lua function acting as a slot
         * @return true if this connection wraps the given Lua function, false otherwise
         */
        bool wrapsSlotFunction(SWIGLUA_REF slot_fn) {
            if (slot_fn.L != _slot_fn.L)
                return false;

            swiglua_ref_get(&_slot_fn);
            swiglua_ref_get(&slot_fn);

            bool result = lua_rawequal(slot_fn.L, -1, -2) == 1;
            lua_pop(_slot_fn.L, 2);

            return result;
        }

    protected:
        /**
         * Return a copy of this connection's slot function.
         *
         * @return copy of this connection's slot function
         */
        SWIGLUA_REF copySlotFunction() {
            SWIGLUA_REF slot_fn;

            {
                LuaStateMutexType::scoped_lock lock(*_lua_state_mutex);

                swiglua_ref_get(&_slot_fn);
                swiglua_ref_set(&slot_fn, _slot_fn.L, -1);
                lua_pop(_slot_fn.L, 1);
            }

            return slot_fn;
        }

        /**
         * Return a dummy destination object.
         *
         * Because Lua connections do not have any destination objects (i.e. slots defined in Lua
         * are not attached to any class), a dummy one has to be created to comply with sigslot's
         * API.
         *
         * @return dummy destination object
         */
204
        has_slots* getDummyDest() const {
205
            if (_dummy_dest == nullptr)
206
                _dummy_dest = new has_slots();
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

            return _dummy_dest;
        }

        /**
         * Call a slot defined in Lua with the provided arguments.
         *
         * @param argWithTypeInfoList list of objects that bundle signal arguments with their SWIG
         *                            type information
         */
        void callLuaSlot(std::list<ArgWithTypeInfoType>* argWithTypeInfoList) {
            /*
             * argWithTypeInfoList is null if type information for some arguments could not be
             * found. In that case an error has been logged already and there's no processing left
             * to be done.
             */
            if (argWithTypeInfoList != nullptr) {
                LuaStateMutexType::scoped_lock lock(*_lua_state_mutex);

                // Put this connection's slot and all arguments on Lua's stack
                swiglua_ref_get(&_slot_fn);

                for (auto it = argWithTypeInfoList->begin(); it != argWithTypeInfoList->end(); ++it)
                    SWIG_NewPointerObj(_slot_fn.L, it->first, it->second, 0);

                if (lua_pcall(_slot_fn.L, argWithTypeInfoList->size(), 0, 0) != LUA_OK) {
                    const char* errorMsg = lua_tostring(_slot_fn.L, -1);

                    if (errorMsg == nullptr)
236
                        LogMgr.log("Lua", cgt::LuaError, "(error object is not a string)");
237
                    else
238
                        LogMgr.log("Lua", cgt::LuaError, "An error occured while calling a Lua slot function: " + std::string(errorMsg));
239
240
241
242
243
244
245
246
247

                    lua_pop(_slot_fn.L, 1);
                }

                delete argWithTypeInfoList;
            }
        }

        SWIGLUA_REF _slot_fn;                          ///< Reference to a Lua function acting as a slot
248
        mutable has_slots* _dummy_dest;                ///< Dummy destination object needed to support getdest()
249
250
251
252
253
        LuaStateMutexType* _lua_state_mutex;           ///< Mutex guarding access to the above function's Lua state
    };

    /**
     * Custom signal-slot connection type for nullary signals that accepts Lua functions as slots.
254
255
256
257
     *
     * The template parameter is just a dummy parameter to enforce that _connection_base0 is always
     * locally instantiated as template and not linked into the sigslot library. This makes writing
     * scripting bindings much easier
258
     */
259
260
    template<int DUMMY_PARAMETER = 0>
    class _lua_connection0 : public _lua_connection_base<>, public _connection_base0
261
262
263
    {
    public:
        _lua_connection0(SWIGLUA_REF slot_fn)
264
            : _lua_connection_base<>(slot_fn)
265
266
267
        {}

        _lua_connection0(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex)
268
            : _lua_connection_base<>(slot_fn, lua_state_mutex)
269
270
        {}

271
272
        virtual _connection_base0* clone() {
            return new _lua_connection0<DUMMY_PARAMETER>(this->copySlotFunction(), this->_lua_state_mutex);
273
274
        }

275
        virtual _connection_base0* duplicate(sigslot::has_slots* pnewdest) {
276
277
278
279
280
281
282
283
            /*
             * Because Lua connections do not have any external destination objects that could be
             * copied (which in turn would require duplicating the connections for the copy), this
             * method should never be invoked.
             */
            return nullptr;
        }

284
        virtual void processSignal() {
285
            std::list<ArgWithTypeInfoType>* argWithTypeInfoList = new std::list<ArgWithTypeInfoType>(0);
286
            this->callLuaSlot(argWithTypeInfoList);
287
288
        }

289
        virtual has_slots* getdest() const {
290
            return this->getDummyDest();
291
292
293
294
295
296
        }
    };

    /**
     * Custom signal-slot connection type for unary signals that accepts Lua functions as slots.
     */
297
298
    template<class arg1_type>
    class _lua_connection1 : public _lua_connection_base<>, public _connection_base1<arg1_type>
299
300
301
    {
    public:
        _lua_connection1(SWIGLUA_REF slot_fn)
302
            : _lua_connection_base<>(slot_fn)
303
304
305
        {}

        _lua_connection1(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex)
306
            : _lua_connection_base<>(slot_fn, lua_state_mutex)
307
308
        {}

309
        virtual _connection_base1<arg1_type>* clone() {
310
            return new _lua_connection1(this->copySlotFunction(), this->_lua_state_mutex);
311
312
        }

313
        virtual _connection_base1<arg1_type>* duplicate(sigslot::has_slots* pnewdest) {
314
315
316
317
318
319
320
321
            /*
             * Because Lua connections do not have any external destination objects that could be
             * copied (which in turn would require duplicating the connections for the copy), this
             * method should never be invoked.
             */
            return nullptr;
        }

322
        virtual void processSignal(arg1_type a1) {
323
            std::list<ArgWithTypeInfoType>* argWithTypeInfoList = getArgWithTypeInfoList<arg1_type>(a1);
324
            this->callLuaSlot(argWithTypeInfoList);
325
326
        }

327
        virtual has_slots* getdest() const {
328
            return this->getDummyDest();
329
330
331
332
333
334
        }
    };

    /**
     * Custom signal-slot connection type for binary signals that accepts Lua functions as slots.
     */
335
336
337
    template<class arg1_type, class arg2_type>
    class _lua_connection2 : public _lua_connection_base<>
                           , public _connection_base2<arg1_type, arg2_type>
338
339
340
    {
    public:
        _lua_connection2(SWIGLUA_REF slot_fn)
341
            : _lua_connection_base<>(slot_fn)
342
343
344
        {}

        _lua_connection2(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex)
345
            : _lua_connection_base<>(slot_fn, lua_state_mutex)
346
347
        {}

348
        virtual _connection_base2<arg1_type, arg2_type>* clone() {
349
            return new _lua_connection2(this->copySlotFunction(), this->_lua_state_mutex);
350
351
        }

352
        virtual _connection_base2<arg1_type, arg2_type>* duplicate(sigslot::has_slots* pnewdest) {
353
354
355
356
357
358
359
360
            /*
             * Because Lua connections do not have any external destination objects that could be
             * copied (which in turn would require duplicating the connections for the copy), this
             * method should never be invoked.
             */
            return nullptr;
        }

361
        virtual void processSignal(arg1_type a1, arg2_type a2) {
362
            std::list<ArgWithTypeInfoType>* argWithTypeInfoList = getArgWithTypeInfoList<arg1_type, arg2_type>(a1, a2);
363
            this->callLuaSlot(argWithTypeInfoList);
364
365
        }

366
        virtual has_slots* getdest() const {
367
            return this->getDummyDest();
368
369
370
371
372
373
        }
    };

    /**
     * Custom signal-slot connection type for ternary signals that accepts Lua functions as slots.
     */
374
375
376
    template<class arg1_type, class arg2_type, class arg3_type>
    class _lua_connection3 : public _lua_connection_base<>
                           , public _connection_base3<arg1_type, arg2_type, arg3_type>
377
378
379
    {
    public:
        _lua_connection3(SWIGLUA_REF slot_fn)
380
            : _lua_connection_base<>(slot_fn)
381
382
383
        {}

        _lua_connection3(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex)
384
            : _lua_connection_base<>(slot_fn, lua_state_mutex)
385
386
        {}

387
        virtual _connection_base3<arg1_type, arg2_type, arg3_type>* clone() {
388
            return new _lua_connection3(this->copySlotFunction(), this->_lua_state_mutex);
389
390
        }

391
        virtual _connection_base3<arg1_type, arg2_type, arg3_type>* duplicate(sigslot::has_slots* pnewdest)
392
393
394
395
396
397
398
399
400
        {
            /*
             * Because Lua connections do not have any external destination objects that could be
             * copied (which in turn would require duplicating the connections for the copy), this
             * method should never be invoked.
             */
            return nullptr;
        }

401
        virtual void processSignal(arg1_type a1, arg2_type a2, arg3_type a3) {
402
403
            std::list<ArgWithTypeInfoType>* argWithTypeInfoList =
                    getArgWithTypeInfoList<arg1_type, arg2_type, arg3_type>(a1, a2, a3);
404
            this->callLuaSlot(argWithTypeInfoList);
405
406
        }

407
        virtual has_slots* getdest() const {
408
            return this->getDummyDest();
409
410
411
412
413
414
        }
    };

    /**
     * Custom signal-slot connection type for 4-ary signals that accepts Lua functions as slots.
     */
415
416
417
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type>
    class _lua_connection4 : public _lua_connection_base<>
                           , public _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type>
418
419
420
    {
    public:
        _lua_connection4(SWIGLUA_REF slot_fn)
421
            : _lua_connection_base<>(slot_fn)
422
423
424
        {}

        _lua_connection4(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex)
425
            : _lua_connection_base<>(slot_fn, lua_state_mutex)
426
427
        {}

428
        virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type>* clone() {
429
            return new _lua_connection4(this->copySlotFunction(), this->_lua_state_mutex);
430
431
        }

432
        virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type>* duplicate(sigslot::has_slots* pnewdest)
433
434
435
436
437
438
439
440
441
        {
            /*
             * Because Lua connections do not have any external destination objects that could be
             * copied (which in turn would require duplicating the connections for the copy), this
             * method should never be invoked.
             */
            return nullptr;
        }

442
        virtual void processSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) {
443
444
            std::list<ArgWithTypeInfoType>* argWithTypeInfoList =
                    getArgWithTypeInfoList<arg1_type, arg2_type, arg3_type, arg4_type>(a1, a2, a3, a4);
445
            this->callLuaSlot(argWithTypeInfoList);
446
447
        }

448
        virtual has_slots* getdest() const {
449
            return this->getDummyDest();
450
451
452
453
454
455
        }
    };

    /**
     * Custom signal-slot connection type for 5-ary signals that accepts Lua functions as slots.
     */
456
457
458
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class arg5_type>
    class _lua_connection5 : public _lua_connection_base<>
                           , public _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>
459
460
461
    {
    public:
        _lua_connection5(SWIGLUA_REF slot_fn)
462
            : _lua_connection_base<>(slot_fn)
463
464
465
        {}

        _lua_connection5(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex)
466
            : _lua_connection_base<>(slot_fn, lua_state_mutex)
467
468
        {}

469
        virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>* clone() {
470
            return new _lua_connection5(this->copySlotFunction(), this->_lua_state_mutex);
471
472
        }

473
        virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>* duplicate(sigslot::has_slots* pnewdest)
474
475
476
477
478
479
480
481
482
        {
            /*
             * Because Lua connections do not have any external destination objects that could be
             * copied (which in turn would require duplicating the connections for the copy), this
             * method should never be invoked.
             */
            return nullptr;
        }

483
        virtual void processSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5) {
484
485
            std::list<ArgWithTypeInfoType>* argWithTypeInfoList =
                    getArgWithTypeInfoList<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>(a1, a2, a3, a4, a5);
486
            this->callLuaSlot(argWithTypeInfoList);
487
488
        }

489
        virtual has_slots* getdest() const {
490
            return this->getDummyDest();
491
492
493
494
495
496
497
498
499
500
501
        }
    };

}
}

namespace sigslot {

    class signal0 {
    public:
        signal0();
502
503
        signal0(const sigslot::signal0& s);
        virtual ~signal0();
504
505
506
507
508
509
510
511

        %extend {
            /**
             * Connect this signal to a Lua function.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void connect(SWIGLUA_REF slot_fn) {
512
                sigslot::_lua_connection0<>* conn = new sigslot::_lua_connection0<>(slot_fn);
513
514
515
516
517
518
519
520
521
                $self->m_connected_slots.push_back(conn);
            }

            /**
             * Disconnect a Lua function from this signal.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void disconnect(SWIGLUA_REF slot_fn) {
522
                typedef sigslot::_signal_base0::connections_list connections_list;
523
524
525
526
                connections_list::iterator it = $self->m_connected_slots.begin();
                connections_list::iterator itEnd = $self->m_connected_slots.end();

                while (it != itEnd) {
527
528
                    sigslot::_lua_connection0<>* lua_connection =
                            dynamic_cast<sigslot::_lua_connection0<>*>(*it);
529
530
531
532
533
534
535
536
537
538
539
540
541

                    if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) {
                        delete lua_connection;
                        $self->m_connected_slots.erase(it);
                        return;
                    }

                    ++it;
                }
            }
        }
    };

542
    template<class arg1_type>
543
544
545
    class signal1 {
    public:
        signal1();
546
547
        signal1(const sigslot::signal1<arg1_type>& s);
        virtual ~signal1();
548
549
550
551
552
553
554
555

        %extend {
            /**
             * Connect this signal to a Lua function.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void connect(SWIGLUA_REF slot_fn) {
556
557
                sigslot::_lua_connection1<arg1_type>* conn =
                    new sigslot::_lua_connection1<arg1_type>(slot_fn);
558
559
560
561
562
563
564
565
566
                $self->m_connected_slots.push_back(conn);
            }

            /**
             * Disconnect a Lua function from this signal.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void disconnect(SWIGLUA_REF slot_fn) {
567
                typedef sigslot::_signal_base1<arg1_type>::connections_list connections_list;
568
569
570
571
572

                connections_list::iterator it = $self->m_connected_slots.begin();
                connections_list::iterator itEnd = $self->m_connected_slots.end();

                while (it != itEnd) {
573
574
                    sigslot::_lua_connection1<arg1_type>* lua_connection =
                            dynamic_cast<sigslot::_lua_connection1<arg1_type>*>(*it);
575
576
577
578
579
580
581
582
583
584
585
586
587

                    if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) {
                        delete lua_connection;
                        $self->m_connected_slots.erase(it);
                        return;
                    }

                    ++it;
                }
            }
        }
    };

588
    template<class arg1_type, class arg2_type>
589
590
591
    class signal2 {
    public:
        signal2();
592
593
        signal2(const sigslot::signal2<arg1_type, arg2_type>& s);
        virtual ~signal2();
594
595
596
597
598
599
600
601

        %extend {
            /**
             * Connect this signal to a Lua function.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void connect(SWIGLUA_REF slot_fn) {
602
603
                sigslot::_lua_connection2<arg1_type, arg2_type>* conn =
                    new sigslot::_lua_connection2<arg1_type, arg2_type>(slot_fn);
604
605
606
607
608
609
610
611
612
                $self->m_connected_slots.push_back(conn);
            }

            /**
             * Disconnect a Lua function from this signal.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void disconnect(SWIGLUA_REF slot_fn) {
613
                typedef sigslot::_signal_base2<arg1_type, arg2_type>::connections_list connections_list;
614
615
616
617
                connections_list::iterator it = $self->m_connected_slots.begin();
                connections_list::iterator itEnd = $self->m_connected_slots.end();

                while (it != itEnd) {
618
619
                    sigslot::_lua_connection2<arg1_type, arg2_type>* lua_connection =
                            dynamic_cast<sigslot::_lua_connection2<arg1_type, arg2_type>*>(*it);
620
621
622
623
624
625
626
627
628
629
630
631
632

                    if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) {
                        delete lua_connection;
                        $self->m_connected_slots.erase(it);
                        return;
                    }

                    ++it;
                }
            }
        }
    };

633
    template<class arg1_type, class arg2_type, class arg3_type>
634
635
636
    class signal3 {
    public:
        signal3();
637
638
        signal3(const sigslot::signal3<arg1_type, arg2_type, arg3_type>& s);
        virtual ~signal3();
639
640
641
642
643
644
645
646

        %extend {
            /**
             * Connect this signal to a Lua function.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void connect(SWIGLUA_REF slot_fn) {
647
648
                sigslot::_lua_connection3<arg1_type, arg2_type, arg3_type>* conn =
                    new sigslot::_lua_connection3<arg1_type, arg2_type, arg3_type>(slot_fn);
649
650
651
652
653
654
655
656
657
                $self->m_connected_slots.push_back(conn);
            }

            /**
             * Disconnect a Lua function from this signal.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void disconnect(SWIGLUA_REF slot_fn) {
658
                typedef sigslot::_signal_base3<arg1_type, arg2_type, arg3_type>::connections_list connections_list;
659
660
661
662
                connections_list::iterator it = $self->m_connected_slots.begin();
                connections_list::iterator itEnd = $self->m_connected_slots.end();

                while (it != itEnd) {
663
664
                    sigslot::_lua_connection3<arg1_type, arg2_type, arg3_type>* lua_connection =
                            dynamic_cast<sigslot::_lua_connection3<arg1_type, arg2_type, arg3_type>*>(*it);
665
666
667
668
669
670
671
672
673
674
675
676
677

                    if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) {
                        delete lua_connection;
                        $self->m_connected_slots.erase(it);
                        return;
                    }

                    ++it;
                }
            }
        }
    };

678
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type>
679
680
681
    class signal4 {
    public:
        signal4();
682
683
        signal4(const sigslot::signal4<arg1_type, arg2_type, arg3_type, arg4_type>& s);
        virtual ~signal4();
684
685
686
687
688
689
690
691

        %extend {
            /**
             * Connect this signal to a Lua function.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void connect(SWIGLUA_REF slot_fn) {
692
693
                sigslot::_lua_connection4<arg1_type, arg2_type, arg3_type, arg4_type>* conn =
                    new sigslot::_lua_connection4<arg1_type, arg2_type, arg3_type, arg4_type>(slot_fn);
694
695
696
697
698
699
700
701
702
                $self->m_connected_slots.push_back(conn);
            }

            /**
             * Disconnect a Lua function from this signal.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void disconnect(SWIGLUA_REF slot_fn) {
703
                typedef sigslot::_signal_base4<arg1_type, arg2_type, arg3_type, arg4_type>::connections_list connections_list;
704
705
706
707
                connections_list::iterator it = $self->m_connected_slots.begin();
                connections_list::iterator itEnd = $self->m_connected_slots.end();

                while (it != itEnd) {
708
709
                    sigslot::_lua_connection4<arg1_type, arg2_type, arg3_type, arg4_type>* lua_connection =
                            dynamic_cast<sigslot::_lua_connection4<arg1_type, arg2_type, arg3_type, arg4_type>*>(*it);
710
711
712
713
714
715
716
717
718
719
720
721
722

                    if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) {
                        delete lua_connection;
                        $self->m_connected_slots.erase(it);
                        return;
                    }

                    ++it;
                }
            }
        }
    };

723
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class arg5_type>
724
725
726
    class signal5 {
    public:
        signal5();
727
728
        signal5(const sigslot::signal5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>& s);
        virtual ~signal5();
729
730
731
732
733
734
735
736

        %extend {
            /**
             * Connect this signal to a Lua function.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void connect(SWIGLUA_REF slot_fn) {
737
738
                sigslot::_lua_connection5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>* conn =
                    new sigslot::_lua_connection5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>(slot_fn);
739
740
741
742
743
744
745
746
747
                $self->m_connected_slots.push_back(conn);
            }

            /**
             * Disconnect a Lua function from this signal.
             *
             * @param slot_fn reference to a Lua function acting as a slot
             */
            void disconnect(SWIGLUA_REF slot_fn) {
748
                typedef sigslot::_signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>::connections_list connections_list;
749
750
751
752
                connections_list::iterator it = $self->m_connected_slots.begin();
                connections_list::iterator itEnd = $self->m_connected_slots.end();

                while (it != itEnd) {
753
                    sigslot::_lua_connection5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>* lua_connection =
754
                            dynamic_cast<sigslot::_lua_connection5<arg1_type, arg2_type, arg3_type, arg4_type,
755
                                                                   arg5_type>*>(*it);
756
757
758
759
760
761
762
763
764
765
766
767
768

                    if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) {
                        delete lua_connection;
                        $self->m_connected_slots.erase(it);
                        return;
                    }

                    ++it;
                }
            }
        }
    };
}