赞
踩
此模块主要实现的是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代码文件加了注释贴出来,能看懂这个文件就能看懂其他文件吧
- /******************************************************************************
- * Copyright 2018 The Apollo Authors. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *****************************************************************************/
-
- #ifndef CYBER_MESSAGE_MESSAGE_TRAITS_H_
- #define CYBER_MESSAGE_MESSAGE_TRAITS_H_
-
- #include <string>
-
- #include "cyber/base/macros.h"
- #include "cyber/common/log.h"
- #include "cyber/message/message_header.h"
- #include "cyber/message/protobuf_traits.h"
- #include "cyber/message/py_message_traits.h"
- #include "cyber/message/raw_message_traits.h"
-
- namespace apollo {
- namespace cyber {
- namespace message {
-
- //写在之前
- //typeid(T).name()在C++里面可以获取任何类型的名字,无论他是int、bool、std::map亦或者是自定义的类
-
- //DEFINE_TYPE_TRAIT宏用法之前文章有详细的描述,在此做个大概介绍HasByteSize<T>::value的bool值可判定T有无ByteSizeLong接口
- //其他以此类推
- DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong)
- DEFINE_TYPE_TRAIT(HasType, TypeName)
- DEFINE_TYPE_TRAIT(HasSetType, SetTypeName)
- DEFINE_TYPE_TRAIT(HasGetDescriptorString, GetDescriptorString)
- DEFINE_TYPE_TRAIT(HasDescriptor, descriptor)
- DEFINE_TYPE_TRAIT(HasFullName, full_name)
- DEFINE_TYPE_TRAIT(HasSerializeToString, SerializeToString)
- DEFINE_TYPE_TRAIT(HasParseFromString, ParseFromString)
- DEFINE_TYPE_TRAIT(HasSerializeToArray, SerializeToArray)
- DEFINE_TYPE_TRAIT(HasParseFromArray, ParseFromArray)
-
- //新建一个模板类,此类可以汇总序列化接口,四个接口必须都有HasSerializer<T>::value的值才为true
- template <typename T>
- class HasSerializer {
- public:
- static constexpr bool value =
- HasSerializeToString<T>::value && HasParseFromString<T>::value &&
- HasSerializeToArray<T>::value && HasParseFromArray<T>::value;
- };
-
- // avoid potential ODR violation
- template <typename T>
- constexpr bool HasSerializer<T>::value;
-
- //七个重载函数MessageType,根据条件1.有无接口TypeName 2.接口是静态接口还是成员接口 3.是否继承自
- //google::protobuf::Message 4.有无函数参数 这四个条件不同情况进行不同6个的重载
- //重载1:有TypeName接口,是成员函数,有函数参数
- template <typename T,
- typename std::enable_if<HasType<T>::value &&
- std::is_member_function_pointer<
- decltype(&T::TypeName)>::value,
- bool>::type = 0>
- std::string MessageType(const T& message) {
- return message.TypeName();
- }
- //重载2:有TypeName接口,不是成员函数(是静态接口),有函数参数
- template <typename T,
- typename std::enable_if<HasType<T>::value &&
- !std::is_member_function_pointer<
- decltype(&T::TypeName)>::value,
- bool>::type = 0>
- std::string MessageType(const T& message) {
- return T::TypeName();
- }
- //重载3:无TypeName接口,不继承自google::protobuf::Message,有函数参数
- template <typename T,
- typename std::enable_if<
- !HasType<T>::value &&
- !std::is_base_of<google::protobuf::Message, T>::value,
- bool>::type = 0>
- std::string MessageType(const T& message) {
- return typeid(T).name();
- }
- //重载4:有TypeName接口,不是成员函数,没函数参数
- template <typename T,
- typename std::enable_if<HasType<T>::value &&
- !std::is_member_function_pointer<
- decltype(&T::TypeName)>::value,
- bool>::type = 0>
- std::string MessageType() {
- return T::TypeName();
- }
- //重载5:无TypeName接口,不继承自google::protobuf::Message,没函数参数
- template <typename T,
- typename std::enable_if<
- !HasType<T>::value &&
- !std::is_base_of<google::protobuf::Message, T>::value,
- bool>::type = 0>
- std::string MessageType() {
- return typeid(T).name();
- }
- //重载6:有TypeName接口,是成员函数(是静态接口),不继承自google::protobuf::Message,没函数参数
- template <
- typename T,
- typename std::enable_if<
- HasType<T>::value &&
- std::is_member_function_pointer<decltype(&T::TypeName)>::value &&
- !std::is_base_of<google::protobuf::Message, T>::value,
- bool>::type = 0>
- std::string MessageType() {
- return typeid(T).name();
- }
- //SetTypeName两个重载,模板参数T有SetTypeName接口就调用,没有就不调用
- template <typename T>
- typename std::enable_if<HasSetType<T>::value, void>::type SetTypeName(
- const std::string& type_name, T* message) {
- message->SetTypeName(type_name);
- }
-
- template <typename T>
- typename std::enable_if<!HasSetType<T>::value, void>::type SetTypeName(
- const std::string& type_name, T* message) {}
- //ByteSize两个重载,模板参数T有ByteSizeLong接口就调用,没有就不调用,直接返回-1
- template <typename T>
- typename std::enable_if<HasByteSize<T>::value, int>::type ByteSize(
- const T& message) {
- return static_cast<int>(message.ByteSizeLong());
- }
-
- template <typename T>
- typename std::enable_if<!HasByteSize<T>::value, int>::type ByteSize(
- const T& message) {
- (void)message;
- return -1;
- }
- //FullByteSize代表消息头+消息体的大小
- template <typename T>
- int FullByteSize(const T& message) {
- int content_size = ByteSize(message);
- if (content_size < 0) {
- return content_size;
- }
- return content_size + static_cast<int>(sizeof(MessageHeader));
- }
- //ParseFromArray两个重载,模板参数T有ParseFromArra接口就调用,没有就不调用,直接返回false
- template <typename T>
- typename std::enable_if<HasParseFromArray<T>::value, bool>::type ParseFromArray(
- const void* data, int size, T* message) {
- return message->ParseFromArray(data, size);
- }
-
- template <typename T>
- typename std::enable_if<!HasParseFromArray<T>::value, bool>::type
- ParseFromArray(const void* data, int size, T* message) {
- return false;
- }
- //ParseFromString两个重载,模板参数T有ParseFromString接口就调用,没有就不调用,直接返回false
- template <typename T>
- typename std::enable_if<HasParseFromString<T>::value, bool>::type
- ParseFromString(const std::string& str, T* message) {
- return message->ParseFromString(str);
- }
-
- template <typename T>
- typename std::enable_if<!HasParseFromString<T>::value, bool>::type
- ParseFromString(const std::string& str, T* message) {
- return false;
- }
- //ParseFromHC两个重载,HC我理解为HeaderContent的缩写,思思为消息头和消息体
- //模板参数T有HasParseFromArray接口就做一番处理,没有直接返回false
- template <typename T>
- typename std::enable_if<HasParseFromArray<T>::value, bool>::type ParseFromHC(
- const void* data, int size, T* message) {
- const auto header_size = sizeof(MessageHeader);
- RETURN_VAL_IF(size < (int)header_size, false);
- const MessageHeader* header = static_cast<const MessageHeader*>(data);
- RETURN_VAL_IF((size - header_size) < header->content_size(), false);
- SetTypeName(header->msg_type(), message);
- return message->ParseFromArray(
- static_cast<const void*>(static_cast<const char*>(data) + header_size),
- header->content_size());
- }
-
- template <typename T>
- typename std::enable_if<!HasParseFromArray<T>::value, bool>::type ParseFromHC(
- const void* data, int size, T* message) {
- return false;
- }
- //SerializeToArray两个重载,模板参数T有SerializeToArray接口就调用,没有就不调用,直接返回false
- template <typename T>
- typename std::enable_if<HasSerializeToArray<T>::value, bool>::type
- SerializeToArray(const T& message, void* data, int size) {
- return message.SerializeToArray(data, size);
- }
-
- template <typename T>
- typename std::enable_if<!HasSerializeToArray<T>::value, bool>::type
- SerializeToArray(const T& message, void* data, int size) {
- return false;
- }
- //SerializeToString两个重载,模板参数T有SerializeToString接口就调用,没有就不调用,直接返回false
- template <typename T>
- typename std::enable_if<HasSerializeToString<T>::value, bool>::type
- SerializeToString(const T& message, std::string* str) {
- return message.SerializeToString(str);
- }
-
- template <typename T>
- typename std::enable_if<!HasSerializeToString<T>::value, bool>::type
- SerializeToString(const T& message, std::string* str) {
- return false;
- }
- //SerializeToHC两个重载,模板参数T有SerializeToArray接口就调用,没有就不调用,直接返回false
- template <typename T>
- typename std::enable_if<HasSerializeToArray<T>::value, bool>::type
- SerializeToHC(const T& message, void* data, int size) {
- int msg_size = ByteSize(message);
- if (msg_size < 0) {
- return false;
- }
- const std::string& type_name = MessageType(message);
- MessageHeader header;
- header.set_msg_type(type_name.data(), type_name.size());
- header.set_content_size(msg_size);
- if (sizeof(header) > static_cast<size_t>(size)) {
- return false;
- }
- char* ptr = reinterpret_cast<char*>(data);
- memcpy(ptr, static_cast<const void*>(&header), sizeof(header));
- ptr += sizeof(header);
- int left_size = size - static_cast<int>(sizeof(header));
- return SerializeToArray(message, reinterpret_cast<void*>(ptr), left_size);
- }
-
- template <typename T>
- typename std::enable_if<!HasSerializeToArray<T>::value, bool>::type
- SerializeToHC(const T& message, void* data, int size) {
- return false;
- }
- //GetDescriptorString三个重载之一,模板T有GetDescriptorString接口,直接调用该接口
- template <typename T, typename std::enable_if<HasGetDescriptorString<T>::value,
- bool>::type = 0>
- void GetDescriptorString(const std::string& type, std::string* desc_str) {
- T::GetDescriptorString(type, desc_str);
- }
- //GetDescriptorString三个重载之一,模板T无GetDescriptorString接口,并且非继承自google::protobuf::Message
- //直接返回false
- template <typename T,
- typename std::enable_if<
- !HasGetDescriptorString<T>::value &&
- !std::is_base_of<google::protobuf::Message, T>::value,
- bool>::type = 0>
- void GetDescriptorString(const std::string& type, std::string* desc_str) {}
- //GetDescriptorString三个重载之一,模板T非继承自google::protobuf::Message
- //直接返回false(这样一看上面那个重载有点多余)
- template <typename MessageT,
- typename std::enable_if<
- !std::is_base_of<google::protobuf::Message, MessageT>::value,
- int>::type = 0>
- void GetDescriptorString(const MessageT& message, std::string* desc_str) {}
- //GetFullName两个重载之一,模板参数Descriptor有full_name接口,利用T::descriptor()获取到Descriptor
- //感觉这个写法并不安全,没后判定模板T一定就有静态接口descriptor
- template <
- typename T, typename Descriptor,
- typename std::enable_if<HasFullName<Descriptor>::value, bool>::type = 0>
- std::string GetFullName() {
- return T::descriptor()->full_name();
- }
- //GetFullName两个重载之二,模板参数Descriptor无full_name接口,
- template <
- typename T, typename Descriptor,
- typename std::enable_if<!HasFullName<Descriptor>::value, bool>::type = 0>
- std::string GetFullName() {
- return typeid(T).name();
- }
-
- //GetFullName三个重载之一,模板参数T有descriptor接口,T并非继承自google::protobuf::Message
- template <typename T,
- typename std::enable_if<
- HasDescriptor<T>::value &&
- !std::is_base_of<google::protobuf::Message, T>::value,
- bool>::type = 0>
- std::string GetMessageName() {
- return GetFullName<T, decltype(*T::descriptor())>();
- }
- //GetFullName三个重载之二,模板参数T有descriptor接口,T继承自google::protobuf::Message
- template <typename T,
- typename std::enable_if<
- HasDescriptor<T>::value &&
- std::is_base_of<google::protobuf::Message, T>::value,
- bool>::type = 0>
- std::string GetMessageName() {
- return T::descriptor()->full_name();
- }
- //GetFullName三个重载之三,模板参数T没有descriptor接口,
- template <typename T,
- typename std::enable_if<!HasDescriptor<T>::value, bool>::type = 0>
- std::string GetMessageName() {
- return typeid(T).name();
- }
-
- } // namespace message
- } // namespace cyber
- } // namespace apollo
-
- #endif // CYBER_MESSAGE_MESSAGE_TRAITS_H_
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。