当前位置:   article > 正文

百度自动驾驶apollo源码解读16:/cyber/message 模块_百度apollo 2.0源码

百度apollo 2.0源码

此模块主要实现的是protobuf的序列化和反序列化的工作,主要包含以下文件:
1.message_header系列(头文件、测试文件):消息头,序列化的时候将次头放在protobuf形成的内存前面,主要记录一些属性值,比如消息序列号、消息体的大小等,message_traits里面有两个接口ParseFromHC和SerializeToHC 就是专用来序列化和反序列化带这种带消息头的数据的,我们知道cyber有三种通讯方式:1.同进程内部 2.同主机跨进程 3.不同主机 值得注意的是只有第一种方式采用的上这种消息头,具体为什么以后在做分析
2.message_traits系列(头文件、测试文件):序列化和反序列化和message的属性设置、查询接口汇总。此文件众多接口存在的意义:cyber收发消息种类总分为三种:
        a.由.proto文件编译生成的,这种消息都是继承自google::protobuf::Message,并且会自带很多接口函数,比如查询、设置字段值的,查询设置整体proto属性值的,比如SetTypeName、ByteSizeLong等,有静态函数,也有成员函数,还有序列化、反序列化的ParseFromArray、ParseFromString、SerializeToArray、SerializeToString等
        b.原始消息RawMessage,有文件raw_message实现,为了统一规范,该类实现了类似protobuf实现的接口函数
        c.用于python通信的PyMessageWrap,由py_message文件实现,原理类似RawMessage。说完了消息种类有三种,第一种还是不定数量的实现,为了给他们提供统一的对外接口,才有了该文件,对模板函数进行多次重载,用于实现不同的消息种类,最后给外面呈现的统一接口名字。
3.protobuf_factory系列(头文件、实现文件、测试文件、traits文件):对消息进行注册和查询,注册主要包括消息、消息描述、消息文件描述等,注册之后就可以根据上述任一值查询到其他值。
4.py_message系列(头文件、测试文件、traits文件):用于python使用cyber通讯的消息体,(个人拙见:traits文件存在意义不大,因为message_traits写的模板类已包含对应的功能)
5.raw_message系列(头文件、测试文件、traits文件):用于普通消息使用cyber通讯的消息体,(个人拙见:traits文件存在意义不大,因为message_traits写的模板类已包含对应的功能)

有个问题:py_message和raw_message两个两个类存在的意义是什么,仿照proto生成方式生成了一些列接口函数,我的最初猜测是除了传递proto消息外多了一种传递格式,按道理来讲proto是跨语言的,也就是说C++和python可以直接通过proto格式通讯,不过后来我看了看python代码好像不是那么回事儿,cyber的python和c++通讯好像离不开py_message,详细请看我的下一篇文章。

我给message_traits.h代码文件加了注释贴出来,能看懂这个文件就能看懂其他文件吧

  1. /******************************************************************************
  2. * Copyright 2018 The Apollo Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *****************************************************************************/
  16. #ifndef CYBER_MESSAGE_MESSAGE_TRAITS_H_
  17. #define CYBER_MESSAGE_MESSAGE_TRAITS_H_
  18. #include <string>
  19. #include "cyber/base/macros.h"
  20. #include "cyber/common/log.h"
  21. #include "cyber/message/message_header.h"
  22. #include "cyber/message/protobuf_traits.h"
  23. #include "cyber/message/py_message_traits.h"
  24. #include "cyber/message/raw_message_traits.h"
  25. namespace apollo {
  26. namespace cyber {
  27. namespace message {
  28. //写在之前
  29. //typeid(T).name()在C++里面可以获取任何类型的名字,无论他是int、bool、std::map亦或者是自定义的类
  30. //DEFINE_TYPE_TRAIT宏用法之前文章有详细的描述,在此做个大概介绍HasByteSize<T>::value的bool值可判定T有无ByteSizeLong接口
  31. //其他以此类推
  32. DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong)
  33. DEFINE_TYPE_TRAIT(HasType, TypeName)
  34. DEFINE_TYPE_TRAIT(HasSetType, SetTypeName)
  35. DEFINE_TYPE_TRAIT(HasGetDescriptorString, GetDescriptorString)
  36. DEFINE_TYPE_TRAIT(HasDescriptor, descriptor)
  37. DEFINE_TYPE_TRAIT(HasFullName, full_name)
  38. DEFINE_TYPE_TRAIT(HasSerializeToString, SerializeToString)
  39. DEFINE_TYPE_TRAIT(HasParseFromString, ParseFromString)
  40. DEFINE_TYPE_TRAIT(HasSerializeToArray, SerializeToArray)
  41. DEFINE_TYPE_TRAIT(HasParseFromArray, ParseFromArray)
  42. //新建一个模板类,此类可以汇总序列化接口,四个接口必须都有HasSerializer<T>::value的值才为true
  43. template <typename T>
  44. class HasSerializer {
  45. public:
  46. static constexpr bool value =
  47. HasSerializeToString<T>::value && HasParseFromString<T>::value &&
  48. HasSerializeToArray<T>::value && HasParseFromArray<T>::value;
  49. };
  50. // avoid potential ODR violation
  51. template <typename T>
  52. constexpr bool HasSerializer<T>::value;
  53. //七个重载函数MessageType,根据条件1.有无接口TypeName 2.接口是静态接口还是成员接口 3.是否继承自
  54. //google::protobuf::Message 4.有无函数参数 这四个条件不同情况进行不同6个的重载
  55. //重载1:有TypeName接口,是成员函数,有函数参数
  56. template <typename T,
  57. typename std::enable_if<HasType<T>::value &&
  58. std::is_member_function_pointer<
  59. decltype(&T::TypeName)>::value,
  60. bool>::type = 0>
  61. std::string MessageType(const T& message) {
  62. return message.TypeName();
  63. }
  64. //重载2:有TypeName接口,不是成员函数(是静态接口),有函数参数
  65. template <typename T,
  66. typename std::enable_if<HasType<T>::value &&
  67. !std::is_member_function_pointer<
  68. decltype(&T::TypeName)>::value,
  69. bool>::type = 0>
  70. std::string MessageType(const T& message) {
  71. return T::TypeName();
  72. }
  73. //重载3:无TypeName接口,不继承自google::protobuf::Message,有函数参数
  74. template <typename T,
  75. typename std::enable_if<
  76. !HasType<T>::value &&
  77. !std::is_base_of<google::protobuf::Message, T>::value,
  78. bool>::type = 0>
  79. std::string MessageType(const T& message) {
  80. return typeid(T).name();
  81. }
  82. //重载4:有TypeName接口,不是成员函数,没函数参数
  83. template <typename T,
  84. typename std::enable_if<HasType<T>::value &&
  85. !std::is_member_function_pointer<
  86. decltype(&T::TypeName)>::value,
  87. bool>::type = 0>
  88. std::string MessageType() {
  89. return T::TypeName();
  90. }
  91. //重载5:无TypeName接口,不继承自google::protobuf::Message,没函数参数
  92. template <typename T,
  93. typename std::enable_if<
  94. !HasType<T>::value &&
  95. !std::is_base_of<google::protobuf::Message, T>::value,
  96. bool>::type = 0>
  97. std::string MessageType() {
  98. return typeid(T).name();
  99. }
  100. //重载6:有TypeName接口,是成员函数(是静态接口),不继承自google::protobuf::Message,没函数参数
  101. template <
  102. typename T,
  103. typename std::enable_if<
  104. HasType<T>::value &&
  105. std::is_member_function_pointer<decltype(&T::TypeName)>::value &&
  106. !std::is_base_of<google::protobuf::Message, T>::value,
  107. bool>::type = 0>
  108. std::string MessageType() {
  109. return typeid(T).name();
  110. }
  111. //SetTypeName两个重载,模板参数T有SetTypeName接口就调用,没有就不调用
  112. template <typename T>
  113. typename std::enable_if<HasSetType<T>::value, void>::type SetTypeName(
  114. const std::string& type_name, T* message) {
  115. message->SetTypeName(type_name);
  116. }
  117. template <typename T>
  118. typename std::enable_if<!HasSetType<T>::value, void>::type SetTypeName(
  119. const std::string& type_name, T* message) {}
  120. //ByteSize两个重载,模板参数T有ByteSizeLong接口就调用,没有就不调用,直接返回-1
  121. template <typename T>
  122. typename std::enable_if<HasByteSize<T>::value, int>::type ByteSize(
  123. const T& message) {
  124. return static_cast<int>(message.ByteSizeLong());
  125. }
  126. template <typename T>
  127. typename std::enable_if<!HasByteSize<T>::value, int>::type ByteSize(
  128. const T& message) {
  129. (void)message;
  130. return -1;
  131. }
  132. //FullByteSize代表消息头+消息体的大小
  133. template <typename T>
  134. int FullByteSize(const T& message) {
  135. int content_size = ByteSize(message);
  136. if (content_size < 0) {
  137. return content_size;
  138. }
  139. return content_size + static_cast<int>(sizeof(MessageHeader));
  140. }
  141. //ParseFromArray两个重载,模板参数T有ParseFromArra接口就调用,没有就不调用,直接返回false
  142. template <typename T>
  143. typename std::enable_if<HasParseFromArray<T>::value, bool>::type ParseFromArray(
  144. const void* data, int size, T* message) {
  145. return message->ParseFromArray(data, size);
  146. }
  147. template <typename T>
  148. typename std::enable_if<!HasParseFromArray<T>::value, bool>::type
  149. ParseFromArray(const void* data, int size, T* message) {
  150. return false;
  151. }
  152. //ParseFromString两个重载,模板参数T有ParseFromString接口就调用,没有就不调用,直接返回false
  153. template <typename T>
  154. typename std::enable_if<HasParseFromString<T>::value, bool>::type
  155. ParseFromString(const std::string& str, T* message) {
  156. return message->ParseFromString(str);
  157. }
  158. template <typename T>
  159. typename std::enable_if<!HasParseFromString<T>::value, bool>::type
  160. ParseFromString(const std::string& str, T* message) {
  161. return false;
  162. }
  163. //ParseFromHC两个重载,HC我理解为HeaderContent的缩写,思思为消息头和消息体
  164. //模板参数T有HasParseFromArray接口就做一番处理,没有直接返回false
  165. template <typename T>
  166. typename std::enable_if<HasParseFromArray<T>::value, bool>::type ParseFromHC(
  167. const void* data, int size, T* message) {
  168. const auto header_size = sizeof(MessageHeader);
  169. RETURN_VAL_IF(size < (int)header_size, false);
  170. const MessageHeader* header = static_cast<const MessageHeader*>(data);
  171. RETURN_VAL_IF((size - header_size) < header->content_size(), false);
  172. SetTypeName(header->msg_type(), message);
  173. return message->ParseFromArray(
  174. static_cast<const void*>(static_cast<const char*>(data) + header_size),
  175. header->content_size());
  176. }
  177. template <typename T>
  178. typename std::enable_if<!HasParseFromArray<T>::value, bool>::type ParseFromHC(
  179. const void* data, int size, T* message) {
  180. return false;
  181. }
  182. //SerializeToArray两个重载,模板参数T有SerializeToArray接口就调用,没有就不调用,直接返回false
  183. template <typename T>
  184. typename std::enable_if<HasSerializeToArray<T>::value, bool>::type
  185. SerializeToArray(const T& message, void* data, int size) {
  186. return message.SerializeToArray(data, size);
  187. }
  188. template <typename T>
  189. typename std::enable_if<!HasSerializeToArray<T>::value, bool>::type
  190. SerializeToArray(const T& message, void* data, int size) {
  191. return false;
  192. }
  193. //SerializeToString两个重载,模板参数T有SerializeToString接口就调用,没有就不调用,直接返回false
  194. template <typename T>
  195. typename std::enable_if<HasSerializeToString<T>::value, bool>::type
  196. SerializeToString(const T& message, std::string* str) {
  197. return message.SerializeToString(str);
  198. }
  199. template <typename T>
  200. typename std::enable_if<!HasSerializeToString<T>::value, bool>::type
  201. SerializeToString(const T& message, std::string* str) {
  202. return false;
  203. }
  204. //SerializeToHC两个重载,模板参数T有SerializeToArray接口就调用,没有就不调用,直接返回false
  205. template <typename T>
  206. typename std::enable_if<HasSerializeToArray<T>::value, bool>::type
  207. SerializeToHC(const T& message, void* data, int size) {
  208. int msg_size = ByteSize(message);
  209. if (msg_size < 0) {
  210. return false;
  211. }
  212. const std::string& type_name = MessageType(message);
  213. MessageHeader header;
  214. header.set_msg_type(type_name.data(), type_name.size());
  215. header.set_content_size(msg_size);
  216. if (sizeof(header) > static_cast<size_t>(size)) {
  217. return false;
  218. }
  219. char* ptr = reinterpret_cast<char*>(data);
  220. memcpy(ptr, static_cast<const void*>(&header), sizeof(header));
  221. ptr += sizeof(header);
  222. int left_size = size - static_cast<int>(sizeof(header));
  223. return SerializeToArray(message, reinterpret_cast<void*>(ptr), left_size);
  224. }
  225. template <typename T>
  226. typename std::enable_if<!HasSerializeToArray<T>::value, bool>::type
  227. SerializeToHC(const T& message, void* data, int size) {
  228. return false;
  229. }
  230. //GetDescriptorString三个重载之一,模板T有GetDescriptorString接口,直接调用该接口
  231. template <typename T, typename std::enable_if<HasGetDescriptorString<T>::value,
  232. bool>::type = 0>
  233. void GetDescriptorString(const std::string& type, std::string* desc_str) {
  234. T::GetDescriptorString(type, desc_str);
  235. }
  236. //GetDescriptorString三个重载之一,模板T无GetDescriptorString接口,并且非继承自google::protobuf::Message
  237. //直接返回false
  238. template <typename T,
  239. typename std::enable_if<
  240. !HasGetDescriptorString<T>::value &&
  241. !std::is_base_of<google::protobuf::Message, T>::value,
  242. bool>::type = 0>
  243. void GetDescriptorString(const std::string& type, std::string* desc_str) {}
  244. //GetDescriptorString三个重载之一,模板T非继承自google::protobuf::Message
  245. //直接返回false(这样一看上面那个重载有点多余)
  246. template <typename MessageT,
  247. typename std::enable_if<
  248. !std::is_base_of<google::protobuf::Message, MessageT>::value,
  249. int>::type = 0>
  250. void GetDescriptorString(const MessageT& message, std::string* desc_str) {}
  251. //GetFullName两个重载之一,模板参数Descriptor有full_name接口,利用T::descriptor()获取到Descriptor
  252. //感觉这个写法并不安全,没后判定模板T一定就有静态接口descriptor
  253. template <
  254. typename T, typename Descriptor,
  255. typename std::enable_if<HasFullName<Descriptor>::value, bool>::type = 0>
  256. std::string GetFullName() {
  257. return T::descriptor()->full_name();
  258. }
  259. //GetFullName两个重载之二,模板参数Descriptor无full_name接口,
  260. template <
  261. typename T, typename Descriptor,
  262. typename std::enable_if<!HasFullName<Descriptor>::value, bool>::type = 0>
  263. std::string GetFullName() {
  264. return typeid(T).name();
  265. }
  266. //GetFullName三个重载之一,模板参数T有descriptor接口,T并非继承自google::protobuf::Message
  267. template <typename T,
  268. typename std::enable_if<
  269. HasDescriptor<T>::value &&
  270. !std::is_base_of<google::protobuf::Message, T>::value,
  271. bool>::type = 0>
  272. std::string GetMessageName() {
  273. return GetFullName<T, decltype(*T::descriptor())>();
  274. }
  275. //GetFullName三个重载之二,模板参数T有descriptor接口,T继承自google::protobuf::Message
  276. template <typename T,
  277. typename std::enable_if<
  278. HasDescriptor<T>::value &&
  279. std::is_base_of<google::protobuf::Message, T>::value,
  280. bool>::type = 0>
  281. std::string GetMessageName() {
  282. return T::descriptor()->full_name();
  283. }
  284. //GetFullName三个重载之三,模板参数T没有descriptor接口,
  285. template <typename T,
  286. typename std::enable_if<!HasDescriptor<T>::value, bool>::type = 0>
  287. std::string GetMessageName() {
  288. return typeid(T).name();
  289. }
  290. } // namespace message
  291. } // namespace cyber
  292. } // namespace apollo
  293. #endif // CYBER_MESSAGE_MESSAGE_TRAITS_H_

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/862644
推荐阅读
相关标签
  

闽ICP备14008679号