nVal++); //发射信号}};class Receiver: public sigslot::has_slots
从网上看到的另一句话,webrtc中的信号槽像是变种的不雅察看者模式,当有信号发送的时候,信号发送者通过遍历本身的所有connect的信号槽,然后执行他们的回调;起初会有为什么需要信号槽 信号槽与普通的函数回调有什么区另外疑问, 小我私家认为信号槽是一种面向东西的回调,当回调涉及到东西,需要考虑到执行东西的生命周期,信号槽这种变种的不雅察看者模式,在接收信号的东西析构导致信号槽析构的时候,会将注册的信号删除(就像是删除注册了的不雅察看者),很好的将信号和其东西的生命周期进行了绑定打点。
正文 一个例子从网上拿了XXDK使用webrtc信号槽的例子,如下:
/************************************************************************* > File Name: main.cpp > Author: > Email: [email protected] > Created Time: Fri 31 Aug 2018 09:38:20 AM CST ************************************************************************/ #include<iostream> #include"sigslot.h" #include<unistd.h> #include<stdio.h> using namespace std; using namespace sigslot; class Sender { public: sigslot::signal2<std::string, int> m_pfnsigDanger; void Panic() { static int nVal = 0; char szVal[20] = {0}; snprintf(szVal, 20, "help--%d", nVal); m_pfnsigDanger(szVal, nVal++); //发射信号 } }; class Receiver: public sigslot::has_slots<> { public: void OnDanger(std::string strMsg, int nVal) { std::cout << "ccc. Receiver::OnDanger(std::string, int)" << std::endl; std::cout << strMsg.c_str() << "==> " << nVal << std::endl; } }; int main() { Sender sender; Receiver recever; sender.m_pfnsigDanger.connect(&recever, &Receiver::OnDanger);//将信号与信号槽相连 while (1) { std::cout << std::endl; std::cout << "==================================> in while..." << std::endl; sender.Panic();//筹算发射信号 sleep(2); } return 0; }首先界说了一个sender和一个receiver,sender作为信号的发送者,类内包罗了一个信号m_pfnsigDanger, recever作为信号的接收者,担任了has_slots这个类, 供给了信号槽用于给信号绑定。使用m_pfnsigDanger.connect(), 将信号连接到receiver的信号槽中去,并设置回调事件的触发还调;
在这个例子中,涉及到的类如下图所示:
对付Sender, 其内部拥有一个signal_with_thread_policy类型的信号东西,signal_with_thread_policy供给模板以生成差别入参类型回调函数的信号感化,并对发送者供给一些简单的使用接口,如发送信号和连接信号;signal_with_thread_policy担任于_signal_base,_signal_base是真正存储连接信号的类,并供给了更多对付信号的控制和措置惩罚惩罚;_signal_base担任自_signal_base_interface,_signal_base_interface供给了外部(如信号槽)打点使用信号的接口;
对付Reserver,其担任了has_slots,就拥有了一个信号槽,其感化是对连接上来的信号进行打点,当信号槽析构的时候,对应的信号也就不复存在;信号槽担任了has_slots_interface,,用于外部对该信号槽的一些打点操纵
一个根基的信号连接和发射的过程如下图所示
接下来仔细分析connect过程;
template <class mt_policy, typename... Args> class signal_with_thread_policy : public _signal_base<mt_policy> { void connect(desttype* pclass, void (desttype::*pmemfun)(Args...)) { lock_block<mt_policy> lock(this); this->m_connected_slots.push_back(_opaque_connection(pclass, pmemfun)); pclass->signal_connect(static_cast<_signal_base_interface*>(this));//将该信号添加到信号槽中 } }首先按照传入的东西指针pclass和信号触发的成员回调函数pmemfun生成opaque_connection,opaque_connection的感化就是生存东西的指针以及回调的成员函数的指针,然后供给接口去挪用东西的成员函数,如下:
class _opaque_connection { private: typedef void (*emit_t)(const _opaque_connection*); template <typename FromT, typename ToT> union union_caster { FromT from; ToT to; }; emit_t pemit; // 回调的成员函数指针 has_slots_interface* pdest; // 东西指针 unsigned char pmethod[16]; public: template <typename DestT, typename... Args> _opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdest(pd) {//结构函数,生存东西指针和模板实例化后的成员函数指针 typedef void (DestT::*pm_t)(Args...); static_assert(sizeof(pm_t) <= sizeof(pmethod), "Size of slot function pointer too large."); std::memcpy(pmethod, &pm, sizeof(pm_t)); typedef void (*em_t)(const _opaque_connection* self, Args...); union_caster<em_t, emit_t> caster2; caster2.from = &_opaque_connection::emitter<DestT, Args...>; //模板实例化Dest类型的emitter函数地点 pemit = caster2.to; //将该实例化的函数地点强转成emit_t类型先生存起来,需要使用的使用,在通过caster 凭据相反的方法转回来 } ... //发射函数 template <typename... Args> void emit(Args... args) const { std::cout << "999. _opaque_connection::emit(Args... args)" << std::endl; typedef void (*em_t)(const _opaque_connection*, Args...); union_caster<emit_t, em_t> caster; caster.from = pemit; //获取模板实例化的emitter()函数地点,强转,挪用 (caster.to)(this, args...); //挪用函数 } private: template <typename DestT, typename... Args> static void emitter(const _opaque_connection* self, Args... args) { typedef void (DestT::*pm_t)(Args...); pm_t pm; std::memcpy(&pm, self->pmethod, sizeof(pm_t)); ///< 成员函数指针拷贝到pm_t (static_cast<DestT*>(self->pdest)->*(pm))(args...); } };温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/31614.html