/* * 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 %{ #include "tbb/recursive_mutex.h" #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 { * static const char* const typeName; * }; * * const char* const LuaConnectionArgTraits::typeName = "campvis::AbstractProcessor *"; */ template 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 ArgWithTypeInfoType; /* * Return an object bundling the provided argument with its SWIG type information. */ template inline ArgWithTypeInfoType getArgWithTypeInfo(T arg) { const char* const typeName = LuaConnectionArgTraits::typeName; swig_type_info* typeInfo = SWIG_TypeQuery(typeName); if (typeInfo == nullptr) { std::cerr << "SWIG wrapper for " << typeName << " not found" << std::endl; } 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* argWithTypeInfoListCons(ArgWithTypeInfoType head, std::list* 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 inline std::list* getArgWithTypeInfoList(T arg) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg), new std::list()); } template inline std::list* getArgWithTypeInfoList(T1 arg1, T2 arg2) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg1), getArgWithTypeInfoList(arg2)); } template inline std::list* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg1), getArgWithTypeInfoList(arg2, arg3)); } template inline std::list* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3, T4 arg4) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg1), getArgWithTypeInfoList(arg2, arg3, arg4)); } template inline std::list* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg1), getArgWithTypeInfoList(arg2, arg3, arg4, arg5)); } template inline std::list* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg1), getArgWithTypeInfoList(arg2, arg3, arg4, arg5, arg6)); } template inline std::list* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg1), getArgWithTypeInfoList(arg2, arg3, arg4, arg5, arg6, arg7)); } template inline std::list* getArgWithTypeInfoList(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) { return argWithTypeInfoListCons(getArgWithTypeInfo(arg1), getArgWithTypeInfoList(arg2, arg3, arg4, arg5, arg6, arg7, arg8)); } // 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. */ template 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(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(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 */ has_slots* getDummyDest() const { if (_dummy_dest == nullptr) _dummy_dest = new has_slots(); 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* 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) std::cerr << "(error object is not a string)" << std::endl; else std::cerr << "An error occured while calling a Lua slot function: " << errorMsg << std::endl; lua_pop(_slot_fn.L, 1); } delete argWithTypeInfoList; } } SWIGLUA_REF _slot_fn; ///< Reference to a Lua function acting as a slot mutable has_slots* _dummy_dest; ///< Dummy destination object needed to support getdest() 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. */ template class _lua_connection0 : public _lua_connection_base, public _connection_base0 { public: _lua_connection0(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection0(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base0* clone() { return new _lua_connection0(copySlotFunction(), _lua_state_mutex); } virtual _connection_base0* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal() { std::list* argWithTypeInfoList = new std::list(0); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for unary signals that accepts Lua functions as slots. */ template class _lua_connection1 : public _lua_connection_base, public _connection_base1 { public: _lua_connection1(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection1(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base1* clone() { return new _lua_connection1(copySlotFunction(), _lua_state_mutex); } virtual _connection_base1* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for binary signals that accepts Lua functions as slots. */ template class _lua_connection2 : public _lua_connection_base , public _connection_base2 { public: _lua_connection2(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection2(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base2* clone() { return new _lua_connection2(copySlotFunction(), _lua_state_mutex); } virtual _connection_base2* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1, arg2_type a2) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1, a2); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for ternary signals that accepts Lua functions as slots. */ template class _lua_connection3 : public _lua_connection_base , public _connection_base3 { public: _lua_connection3(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection3(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base3* clone() { return new _lua_connection3(copySlotFunction(), _lua_state_mutex); } virtual _connection_base3* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1, a2, a3); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for 4-ary signals that accepts Lua functions as slots. */ template class _lua_connection4 : public _lua_connection_base , public _connection_base4 { public: _lua_connection4(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection4(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base4* clone() { return new _lua_connection4(copySlotFunction(), _lua_state_mutex); } virtual _connection_base4* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1, a2, a3, a4); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for 5-ary signals that accepts Lua functions as slots. */ template class _lua_connection5 : public _lua_connection_base , public _connection_base5 { public: _lua_connection5(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection5(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base5* clone() { return new _lua_connection5(copySlotFunction(), _lua_state_mutex); } virtual _connection_base5* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1, a2, a3, a4, a5); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for 6-ary signals that accepts Lua functions as slots. */ template class _lua_connection6 : public _lua_connection_base , public _connection_base6 { public: _lua_connection6(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection6(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base6* clone() { return new _lua_connection6(copySlotFunction(), _lua_state_mutex); } virtual _connection_base6* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1, a2, a3, a4, a5, a6); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for 7-ary signals that accepts Lua functions as slots. */ template class _lua_connection7 : public _lua_connection_base , public _connection_base7 { public: _lua_connection7(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection7(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base7* clone() { return new _lua_connection7(copySlotFunction(), _lua_state_mutex); } virtual _connection_base7* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1, a2, a3, a4, a5, a6, a7); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; /** * Custom signal-slot connection type for 8-ary signals that accepts Lua functions as slots. */ template class _lua_connection8 : public _lua_connection_base , public _connection_base8 { public: _lua_connection8(SWIGLUA_REF slot_fn) : _lua_connection_base(slot_fn) {} _lua_connection8(SWIGLUA_REF slot_fn, LuaStateMutexType* lua_state_mutex) : _lua_connection_base(slot_fn, lua_state_mutex) {} virtual _connection_base8* clone() { return new _lua_connection8(copySlotFunction(), _lua_state_mutex); } virtual _connection_base8* duplicate(sigslot::has_slots* pnewdest) { /* * 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; } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) { std::list* argWithTypeInfoList = getArgWithTypeInfoList(a1, a2, a3, a4, a5, a6, a7, a8); callLuaSlot(argWithTypeInfoList); } virtual has_slots* getdest() const { return getDummyDest(); } }; } } namespace sigslot { template class signal0 { public: signal0(); signal0(const sigslot::signal0& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection0* conn = new sigslot::_lua_connection0(slot_fn); $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) { typedef sigslot::_signal_base0::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection0* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal1 { public: signal1(); signal1(const sigslot::signal1& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection1* conn = new sigslot::_lua_connection1(slot_fn); $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) { typedef sigslot::_signal_base1::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection1* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal2 { public: signal2(); signal2(const sigslot::signal2& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection2* conn = new sigslot::_lua_connection2(slot_fn); $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) { typedef sigslot::_signal_base2::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection2* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal3 { public: signal3(); signal3(const sigslot::signal3& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection3* conn = new sigslot::_lua_connection3(slot_fn); $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) { typedef sigslot::_signal_base3::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection3* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal4 { public: signal4(); signal4(const sigslot::signal4& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection4* conn = new sigslot::_lua_connection4(slot_fn); $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) { typedef sigslot::_signal_base4::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection4* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal5 { public: signal5(); signal5(const sigslot::signal5& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection5* conn = new sigslot::_lua_connection5(slot_fn); $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) { typedef sigslot::_signal_base5::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection5* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal6 { public: signal6(); signal6(const sigslot::signal6& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection6* conn = new sigslot::_lua_connection6(slot_fn); $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) { typedef sigslot::_signal_base6::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection6* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal7 { public: signal7(); signal7(const sigslot::signal7& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection7* conn = new sigslot::_lua_connection7(slot_fn); $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) { typedef sigslot::_signal_base7::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection7* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; template class signal8 { public: signal8(); signal8(const sigslot::signal8& s); %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) { sigslot::lock_block_write lock($self); sigslot::_lua_connection8* conn = new sigslot::_lua_connection8(slot_fn); $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) { typedef sigslot::_signal_base8::connections_list connections_list; sigslot::lock_block_write lock($self); connections_list::iterator it = $self->m_connected_slots.begin(); connections_list::iterator itEnd = $self->m_connected_slots.end(); while (it != itEnd) { sigslot::_lua_connection8* lua_connection = dynamic_cast*>(*it); if (lua_connection != nullptr && lua_connection->wrapsSlotFunction(slot_fn)) { delete lua_connection; $self->m_connected_slots.erase(it); return; } ++it; } } } }; }