当前位置: 首页 > news >正文

SOME/IP 序列化问题

SOMEIP报文分为Header和Payload两部分,如下图。

其中Payload部分,在Serialize后会在Payload头部填充TLV Tag(4Byte)和BOM(3Byte)。

传输的字符串是someData.Data = "aaaaaaaaaaaaaaaaaaaa";  20个a

payload中 00 00 00 18 ef bb bf

前面一部分是00 00 00 18    (十六进制的18)

ef bb bf 对应的是BOM[0]  BOM[1]   BOM[2]

说明: BOM+实际数据的长度 = 24(BOM 3个字节 + 20个a + 1个 \0)

即使hasTlvTag确实是false,也会保留这个位置,只是里面填写00

import AUTOSAR.StdTypes.uint8_t
import AUTOSAR.StdTypes.stringpackage etas.com {interface AraCM_TLV namespace etas.com {event DataPublisher of DataMessagemethod DataIO (in message (tlvId:33) of string, out value(tlvId:44) of uint8_t)}        // if tlv is configured, all members must have tlvids and the ids are unique          struct DataMessage {DataArray(tlvId:11)  of optional<array<uint8_t, 256>>DataString(tlvId:22) of optional<string>}  /* The definition of Software Components in the Application Design including the provided and required ports categorized by the relevant ServiceInterfaces are now mandatory for the services definition. */ component Publisher_Component {provide PPort for AraCM_TLV}component Subscriber_Component {require RPort for AraCM_TLV}
}

Method ID =7f    ----> 127  

https://blog.csdn.net/hammershr2012/article/details/131073325

/*** \\file  aracm_event_serializer.h** \\authors  This file was generated with VRTE Flexible Safety - Manifest to Adaptive Runtime API Generator * * \\brief    Header File for service specific serializer**/#ifndef ETAS_COM_ARACM_EVENT_SERIALIZER_HPP_INCLUDED
#define ETAS_COM_ARACM_EVENT_SERIALIZER_HPP_INCLUDED#include "etas/com/aracm_event_common.h"#include "serializer/SerializerUtils.hpp"
#include "serializer/SerializeBasicTypes.hpp"
#include "serializer/DeserializeBasicTypes.hpp"
#include "serializer/IDeserializer.hpp"
#include "serializer/ISerializer.hpp"#include <cstring>namespace etas {
namespace com {
namespace aracm_event_SD {
// RULECHECKER_comment(2, 1, check_single_use_pod_variable, "Variable used for possible creation of interface components.", true)
// coverity[autosar_cpp14_a0_1_1_violation:FALSE] Variable used for possible creation of interface components.
static constexpr uint8_t sizeUnionTypeField{1U};
// RULECHECKER_comment(2, 1, check_single_use_pod_variable, "Variable used for possible creation of interface components.", true)
// coverity[autosar_cpp14_a0_1_1_violation:FALSE] Variable used for possible creation of interface components.
static constexpr ::com::serializer::SerializerSettings someipSettings {::com::serializer::ByteOrder::kBigEndian,4U,4U,4U,4U,0U,4U,false};// Note: For TLV-enabled IPC deployments where struct data types are used, the value of the size of the struct length
// field will be overwritten to 4 bytes. This is done to include a length field for handling optional members,
// simplifying the implementation by using a 4-byte length field for all TLV-structs. Even though the value is set to 0
// here, it will be modified during runtime if the conditions for TLV serialization are met.
// RULECHECKER_comment(2, 1, check_single_use_pod_variable, "Variable used for possible creation of interface components.", true)
// coverity[autosar_cpp14_a0_1_1_violation:FALSE] Variable used for possible creation of interface components.
static constexpr ::com::serializer::SerializerSettings ipcSettings {::com::serializer::ByteOrder::kOpaque,4U,0U,4U,4U,0U,4U,false};class Serializer_DataPublisher : public ::com::serializer::ISerializer<DataMessage>
{
private:::com::serializer::SerializerSettings settings_;ara::com::DeploymentType deploymentType_;public:Serializer_DataPublisher(::com::serializer::SerializerSettings settings, ara::com::DeploymentType deploymentType) : ::com::serializer::ISerializer<DataMessage>(), settings_(settings), deploymentType_(deploymentType){}private:// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, a serializer with a void sampleType is used. Refactor in #72627.// coverity[autosar_cpp14_a0_1_3_violation:FALSE] The method is used.uint32_t computeSerializedSize(const DataMessage* objectp, uint8_t& lengthFieldSize, const bool hasTlvTag){uint32_t length{0U};
//        // coverity[autosar_cpp14_a4_7_1_violation] Since the inputs are guaranteed not to exceed the maximum range of uint32_t, the calculation will not cause wrap-around.
//        length += ::com::serializer::computeSerializedSize(objectp->Data, settings_); // STRING
//        // coverity[autosar_cpp14_a0_1_1_violation:FALSE] The variable is used.
//        lengthFieldSize = (settings_.isDynamicLengthFieldSize && hasTlvTag) ? ::com::serializer::computeSizeOfLengthField(length) : settings_.sizeStructLengthField;
//        // coverity[autosar_cpp14_a4_7_1_violation] Since the inputs are guaranteed not to exceed the maximum range of uint32_t, the calculation will not cause wrap-around.
//        length += lengthFieldSize;length = objectp->Data.length() + 1;
//        std::cout << "=================================================" << std::endl;
//        std::cout << "31. length = " << length << std::endl;return length;}public:// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627.// coverity[autosar_cpp14_a0_1_3_violation:FALSE] The method is used.uint32_t computeSerializedSize(const DataMessage* objectp) override{// coverity[autosar_cpp14_m3_4_1_violation] The declaration is preferred here for better readability and maintainance.// coverity[autosar_cpp14_a0_1_1_violation] The variable is used.uint8_t lengthFieldSize{0U};return computeSerializedSize(objectp, lengthFieldSize, false);}// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627.// coverity[autosar_cpp14_a0_1_3_violation:FALSE] The method is used.uint32_t computeSerializedSizeTlv(const DataMessage* objectp, uint8_t &lengthFieldSizeOut) override{return computeSerializedSize(objectp, lengthFieldSizeOut, true);}private:// RULECHECKER_comment(4, 1, check_max_cyclomatic_complexity, "Generated code, the number of cyclomatic complexity is not relevant. For understandability, do not modify.", true)// RULECHECKER_comment(3, 1, check_max_instructions, "Generated code, the number of instructions is not relevant. For understandability, do not modify.", true)// RULECHECKER_comment(2, 1, check_max_parameters, "Generated code, the number of parameters complexity is not relevant.", true)// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627./*bool serialize(uint8_t* targetbuffer, uint32_t maxsize, const DataMessage* objectp, const bool hasTlvTag){// coverity[autosar_cpp14_a0_1_1_violation:FALSE] The value assigned to the variable is used.uint32_t length{0U};uint32_t total_written{0U};// coverity[autosar_cpp14_m3_4_1_violation] The declaration is preferred here for better readability and maintainance.// coverity[autosar_cpp14_a0_1_1_violation] The variable is used.uint8_t lengthFieldSize{0U};// Ensure that the buffer has enough space for the struct size that we want to prepend at the end// coverity[autosar_cpp14_m3_4_1_violation] The declaration is preferred here for better readability and maintainance.// coverity[autosar_cpp14_a0_1_1_violation] The variable is used.total_written = (settings_.isDynamicLengthFieldSize && hasTlvTag) ? 0U : settings_.sizeStructLengthField;// serialize STRING of type stringlength = ::com::serializer::computeSerializedSize(objectp->Data, settings_);// coverity[autosar_cpp14_a4_7_1_violation] Since the inputs are guaranteed not to exceed the maximum range of uint32_t, the calculation will not cause wrap-around.if ((length + total_written) > maxsize){return false;}// coverity[autosar_cpp14_m5_0_15_violation:FALSE] The pointer is arithmetic happens here only with indexing operator, which is compliant.if (!::com::serializer::serialize(objectp->Data, &targetbuffer[total_written], length, settings_)){return false;}// coverity[autosar_cpp14_a0_1_1_violation:FALSE] The value assigned to the variable is used.total_written += length;if (settings_.isDynamicLengthFieldSize && hasTlvTag){// coverity[autosar_cpp14_a0_1_1_violation:FALSE] The variable is used.lengthFieldSize = ::com::serializer::computeSizeOfLengthField(total_written);// Check if there is enough space to prepend the length field// coverity[autosar_cpp14_a4_7_1_violation] Since the inputs are guaranteed not to exceed the maximum range of uint32_t, the calculation will not cause wrap-around.if (lengthFieldSize + total_written > maxsize){return false;}// Shift the serialized data to make space for the length field// coverity[autosar_cpp14_m5_0_15_violation] The pointer is managed by std::memmove in this case. No workaround when using C-style pointers.std::memmove(targetbuffer + lengthFieldSize, targetbuffer, total_written);if(!::com::serializer::writeLengthField(lengthFieldSize, total_written, &targetbuffer, settings_.byteOrder)){return false;}}else if (0U != settings_.sizeStructLengthField){// coverity[autosar_cpp14_a0_1_1_violation:FALSE] The variable is used.lengthFieldSize = settings_.sizeStructLengthField;// Subtract the length field size from total_written before writing// coverity[autosar_cpp14_a4_7_1_violation] Since the inputs are guaranteed not to exceed the maximum range of uint32_t, the calculation will not cause wrap-around.total_written -= lengthFieldSize;if (!::com::serializer::writeLengthField(lengthFieldSize, total_written, &targetbuffer, settings_.byteOrder)){return false;}}return true;}*//*** @brief 将 DataMessage 对象序列化到目标缓冲区。** 此函数将 objectp->Data 字符串的内容复制到 targetbuffer 中,* 并在末尾添加空终止符。它会检查缓冲区大小以防止溢出。** @param targetbuffer 指向目标缓冲区的指针。* @param maxsize 目标缓冲区的最大大小。* @param objectp 指向要序列化的 DataMessage 对象的指针。* @param hasTlvTag (当前实现中未使用,保留以匹配原函数签名)* @return 如果序列化成功则返回 true,如果缓冲区太小则返回 false。*/bool serialize(uint8_t* targetbuffer, uint32_t maxsize, const DataMessage* objectp, const bool hasTlvTag){// 忽略未使用的参数,避免编译器警告(void)hasTlvTag;// 检查输入有效性if (!targetbuffer || !objectp || maxsize == 0) {std::cout << "serialize invalid data "  << std::endl;std::cout << "maxsize = " << maxsize << std::endl;return false;}// 获取数据长度uint32_t data_length = static_cast<uint32_t>(objectp->Data.length());
//    	std::cout << "=====================================================" << std::endl;
//    	std::cout << "1. data_length = " << data_length << std::endl;
//    	std::cout << "2. maxsize = " << maxsize << std::endl;
//    	std::cout << "3. hasTlvTag = " << hasTlvTag << std::endl;std::memcpy(targetbuffer, objectp->Data.c_str(), data_length);targetbuffer[data_length+1] = '\0';return true;}public:/* RULECHECKER_comment(2, 1, check_max_parameters, "Generated code, the number of parameters complexity is not relevant.", true) */// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627.// coverity[autosar_cpp14_a0_1_3_violation:FALSE] This function is called by serialize function of public.bool serialize(uint8_t* targetbuffer, uint32_t maxsize, const DataMessage* objectp) override{return serialize(targetbuffer, maxsize, objectp, false);}/* RULECHECKER_comment(2, 1, check_max_parameters, "Generated code, the number of parameters complexity is not relevant.", true) */// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627.// coverity[autosar_cpp14_a0_1_3_violation:FALSE] This function is called by serialize function of public.bool serializeTlv(uint8_t* targetbuffer, uint32_t maxsize, const DataMessage* objectp) override{return serialize(targetbuffer, maxsize, objectp, true);}
};class Deserializer_DataPublisher : public ::com::serializer::IDeserializer<DataMessage>
{
private:::com::serializer::SerializerSettings settings_;ara::com::DeploymentType deploymentType_;public:Deserializer_DataPublisher(::com::serializer::SerializerSettings settings, ara::com::DeploymentType deploymentType) : ::com::serializer::IDeserializer<DataMessage>(), settings_(settings), deploymentType_(deploymentType){}private:/* RULECHECKER_comment(2, 1, check_max_parameters, "Generated code, the number of parameters complexity is not relevant.", true) */// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627.//    bool deserialize(const uint8_t* receivebuffer, uint32_t length, DataMessage* objectp, uint32_t& readbytes, uint8_t lengthFieldSize)
//    {
//        uint32_t readLength{0U};
//        // coverity[autosar_cpp14_a0_1_1_violation:FALSE] The value assigned to the variable is used.
//        uint32_t subreadbytes{0U};
//        // coverity[autosar_cpp14_a0_1_1_violation:FALSE] The value assigned to the variable is used.
//        uint32_t structLength{0U};
//
//        if (0U == lengthFieldSize)
//        {
//            // coverity[autosar_cpp14_a0_1_1_violation:FALSE] The variable is used.
//            lengthFieldSize = settings_.sizeStructLengthField;
//        }
//
//        if (lengthFieldSize > length)
//        {
//            return false;
//        }
//        // coverity[autosar_cpp14_m0_1_9_violation] The else case for no length field not needed: The static length field size must be non-zero for TLV during configuration.
//        // coverity[autosar_cpp14_m0_1_2_violation] The else case for no length field not needed: The static length field size must be non-zero for TLV during configuration.
//        if (0U != lengthFieldSize)
//        {
//            ::com::serializer::readLengthField(lengthFieldSize, structLength, &receivebuffer, settings_.byteOrder);
//            // coverity[autosar_cpp14_a0_1_1_violation:FALSE] The variable is used.
//            // coverity[autosar_cpp14_m0_1_9_violation:FALSE] The variable is used.
//            length -= lengthFieldSize;
//        }
//
//        // coverity[autosar_cpp14_m5_0_15_violation:FALSE] The pointer is arithmetic happens here only with indexing operator, which is compliant.
//        // coverity[autosar_cpp14_m5_0_15_violation:FALSE] The pointer is arithmetic happens here only with indexing operator, which is compliant.
//        if (!::com::serializer::deserialize(objectp->Data, &receivebuffer[readLength], length - readLength, settings_, subreadbytes))
//        {
//            return false;
//        }
//        readLength += subreadbytes;
//        if (0U != lengthFieldSize)
//        {
//            /* If there is any additional data at the end of the struct that the receiver does not recognize,
//             * the data will be discarded and the deserialize function will return true (SWS_CM_10219).
//             * If there is not enough data to deserialize, the deserialize function will return false. */
//            if (readLength > structLength)
//            {
//                // coverity[autosar_cpp14_m0_1_2_violation] The code is reachable when there is not enough data to deserialize.
//                return false;
//            }
//            readbytes = structLength + lengthFieldSize;
//        }
//        else
//        {
//            // coverity[autosar_cpp14_m0_1_9_violation] If the length of the field or struct field is 0, this code block will be reached.
//            // coverity[autosar_cpp14_m0_1_2_violation] If deserialization happens successfully, this code block will be reached.
//            readbytes = readLength;
//        }
//
//        return true;
//    }bool deserialize(const uint8_t* receivebuffer, uint32_t length, DataMessage* objectp, uint32_t& readbytes, uint8_t lengthFieldSize){// 忽略未使用的参数,避免编译器警告(void)lengthFieldSize;// 检查输入有效性if (!receivebuffer || !objectp || length == 0) {readbytes = 0;return false;}// 在指定长度范围内查找字符串终止符 '\0'const void* null_pos = std::memchr(receivebuffer, '\0', length);// 如果未找到终止符,则输入数据无效或不完整if (null_pos == nullptr) {readbytes = 0; // 或者可以设为 length,取决于错误处理策略return false;}// 计算字符串长度(不包括终止符)uint32_t str_length = static_cast<uint32_t>(static_cast<const uint8_t*>(null_pos) - receivebuffer);// 使用构造函数或 assign 方法一次性设置字符串,效率更高// 注意:str_length 已经是不包含 '\0' 的长度objectp->Data.assign(reinterpret_cast<const char*>(receivebuffer), str_length);// 计算总共读取的字节数(包括终止符 '\0')readbytes = str_length + 1;return true;}public:/* RULECHECKER_comment(3, 1, check_max_parameters, "Generated code, the number of parameters complexity is not relevant.", true) */// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627.// coverity[autosar_cpp14_a0_1_3_violation:FALSE] This function is called by deserialize function of public.bool deserialize(const uint8_t* receivebuffer, uint32_t length, DataMessage* objectp, uint32_t& readbytes) override{return deserialize(receivebuffer, length, objectp, readbytes, 0U);}/* RULECHECKER_comment(3, 1, check_max_parameters, "Generated code, the number of parameters complexity is not relevant.", true) */// coverity[autosar_cpp14_a8_4_10_violation] Changing this to a reference causes a compiler error: "Forming reference to void." This is because for methods that have no return type, we use a serializer with a void sampleType. Refactor in #72627.// coverity[autosar_cpp14_a0_1_3_violation:FALSE] This function is called by deserialize function of public.bool deserializeTlv(const uint8_t* receivebuffer, uint32_t length, DataMessage* objectp, uint32_t& readbytes, uint8_t lengthFieldSize) override{return deserialize(receivebuffer, length, objectp, readbytes, lengthFieldSize);}
};} // namespace aracm_event_SD
} // namespace com
} // namespace etas#endif // ETAS_COM_ARACM_EVENT_SERIALIZER_HPP_INCLUDED
  1. 代码生成后,手动修改序列化的代码
  2. 修改完代码后需要把图中的这一行注释掉

3)编译命令:

rvbuild -sd AraCM_Event_String/ 20

rvbuild -ld AraCM_Event_String/ 21

4)结果:

http://www.dtcms.com/a/540205.html

相关文章:

  • 【Rust编程:从新手到大师】 Rust 所有权与内存安全
  • wordpress如何添加背景音乐seo点评类网站
  • Flink Keyed State 详解之二
  • AI IN ALL王炸霸屏|战神数科与腾讯字节等深度践行AI
  • 【技术干货】在Stimulsoft中使用Google Sheets作为数据源创建报表与仪表盘
  • PCIe协议之唤醒篇之 WAKE# 信号
  • 搜狗做网站怎么样做静态网站有什么用
  • 潍坊网站建设公司哪家好大庆+网站建设
  • 推理成本吞噬AI未来,云计算如何平衡速度与成本的难题?
  • 基于VaR模型的ETF日内动态止损策略实现与理论验证
  • Linux云计算基础篇(28)-Samba文件服务
  • 学习经验分享【42】数学建模大赛参赛经历
  • 5.3 大数据方法论与实践指南-存储成本优化(省钱)
  • 运营商网站服务密码搜索引擎优化seo信息
  • 【案例实战】鸿蒙元服务开发实战:从云原生到移动端,包大小压缩 96% 启动提速 75% 的轻量化设计
  • 网站开发人员介绍网络营销研究现状文献综述
  • html5制作网站一个网站建立团队大概要多少钱
  • AceContainer类中用于初始化任务执行系统的核心方法--AceContainer::InitializeTask
  • Ubuntu部署 Kubernetes1.23
  • 悟空 AI CRM 的回访功能:深化客户关系,驱动业务增长
  • Qt的.pro文件中INSTALLS的作用和用法
  • 我的项目该选LoRa还是RF超短波全数字加密传输?
  • vue3 实现记事本手机版01
  • 03_全连接神经网络
  • 生成式AI重塑教学生态:理论基础、核心特征与伦理边界
  • html5手机网站调用微信分享wordpress缩略图加载慢
  • 动环监控:数据中心机房的“智慧守护者”
  • 5.6对象
  • 生命线与黑箱:LIME和Anchor作为两种事后可解释性分析
  • VMware安装配置CentOS 7