今天在浏览mavros代码的过程中,发现了以下的为特定类型数据包的处理函数注册回调的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
/** * Make subscription to raw message. * * @param[in] id message id * @param[in] fn pointer to member function (handler) */ template<class _C> HandlerInfo make_handler(const mavlink::msgid_t id, void (_C::*fn)(const mavlink::mavlink_message_t *msg, const mavconn::Framing framing)) { auto bfn = std::bind(fn, static_cast<_C*>(this), std::placeholders::_1, std::placeholders::_2); const auto type_hash_ = typeid(mavlink::mavlink_message_t).hash_code(); return HandlerInfo{ id, nullptr, type_hash_, bfn }; } /** * Make subscription to message with automatic decoding. * * @param[in] fn pointer to member function (handler) */ template<class _C, class _T> HandlerInfo make_handler(void (_C::*fn)(const mavlink::mavlink_message_t*, _T&)) { auto bfn = std::bind(fn, static_cast<_C*>(this), std::placeholders::_1, std::placeholders::_2); const auto id = _T::MSG_ID; const auto name = _T::NAME; const auto type_hash_ = typeid(_T).hash_code(); return HandlerInfo{ id, name, type_hash_, [bfn](const mavlink::mavlink_message_t *msg, const mavconn::Framing framing) { if (framing != mavconn::Framing::ok) return; mavlink::MsgMap map(msg); _T obj; obj.deserialize(map); bfn(msg, obj); } }; } |
在make_handler内的lambda表达式中,将统一的类型 mavlink_message_t 通过其自己的方式,转换成回调函数定义中的_T类型(_T类型可以从mavlink_message_t数据包中,解析出各种特化的数据包(如解析成mavlink协议中的Attitude数据包,Altitude数据包,都是不同的_T类型,这些_T类型都可以进行deserialize操作,可以方便地从mavlink协议的定义文件生成对应的代码)(不过这里也同样适用于存在继承关系的场合,直接static_cast过去啦))
而 make_handler 函数,通过对于函数指针的模板类型推导,直接获取了这个函数所要处理的数据格式进行绑定,免去了手动输入要绑定的消息类型的麻烦,是函数中的豪杰.
PS:这种方式似乎也挺方便与Rx风格的Observable<_T>()共存(转换)的…
PS2:好水好水,过几天做个对模板类型推导的详细说明吧….~
PS3:都12天没更新了!!!<-没救
PS4:封面画师 f7(eiki) …(现在似乎不再使用这种画风了….)(心象幻想乡….)