我正在尝试构建和编写二进制请求,并且有一个“这是可能的”类型问题。对我来说,提到请求的接收者并不知道我在下面包含的数据结构可能是很重要的,它只是期望一个字节序列,但使用结构似乎是一种方便的方式来准备请求的各个部分,然后轻松写下来。
编写页眉和页脚很好,因为它们是固定大小但由于向量,我遇到了结构“详细信息”的问题。现在我写一个文件,所以我可以检查请求是规格,但意图是使用boost asio串口最终写入PLC
我可以使用这样的语法来编写结构,但是当它到达向量时会写入指针地址而不是值
myFile.write((char*) &myDataRequest, drSize);
我可以使用这个sytax自己编写一个向量,但我必须将索引器包含在0以写入值
myFile.write((char*) &myVector[0], vectorSize);
是否有一种优雅的方式来二进制编写包含向量(或其他合适的集合)的结构,一次性完成它?比方说,如果我以不同的方式声明了向量,或者我已经辞职为结构内的内容进行多次写入。如果我用数组替换向量,我可以一次性发送结构(不需要包含任何索引器)但我不知道所需的大小,直到运行时所以我认为它不合适。
我的结构
struct Header
{ ... };
struct Details
{
std::vector<DataRequest> DRList;
};
struct DataRequest
{
short numAddresses; // Number of operands to be read Bytes 0-1
unsigned char operandType; // Byte 2
unsigned char Reserved1; //Should be 0xFF Byte 3
std::vector<short> addressList; // either, starting address (for sequence), or a list of addresses (for non-sequential)
};
struct Footer
{ ... };
答案 0 :(得分:2)
这是不可能的,因为std::vector
对象实际上并不包含数组,而是指向内存块的指针。但是,我很想声称能够编写这样的原始结构是不可取的:
我相信通过将结构视为内存块,您可能最终会发送填充字节,我认为这不是必需的。
根据您所写的内容,您可能会发现写入仍然是缓冲的,因此多次写入调用的效率实际上并不低。
您可能希望使用正在发送的字段执行某些内容。特别是,使用您发送的数值。这需要强制执行传输双方同意的字节顺序。为了便于携带,您应该快速转换字节顺序以确保您的软件是可移植的(如果需要)。
长话短说:我怀疑逐个写出每个字段的效率并不低,也更正确。
答案 1 :(得分:1)
这不是一个好策略,因为即使您可以这样做,您也可以将内存内容直接复制到文件中。如果您更改架构/处理器,您的客户端将获得不同的数据。如果你编写一个方法来获取你的struct和一个文件名,它单独写入structs值并迭代向量写出它的内容,你就可以完全控制你的客户期望的二进制格式,而不依赖于编译器当前记忆表示。
如果您想为编组/解组提供便利,您应该查看boost::serialization库。它们确实提供了二进制存档(除了text和xml),但它有自己的格式(例如它有一个版本号,序列化lib用于转储数据),所以它可能不是你客户想要的。
答案 2 :(得分:1)
另一端预期的格式究竟是什么?你必须写
那个时期。你不能只写任何随机字节。概率
只写你正在做的std::vector
就行了
尽可能接近0。但写作的概率
仅struct
只有int
的{{1}}仍然不到50%。如果对方
期望一个特定的字节序列,然后你必须写
该序列,逐字节。例如,要编写int
,您必须这样做
仍然写四个(或协议要求的)字节,东西
像:
byte[0] = (value >> 24) & 0xFF;
byte[1] = (value >> 16) & 0xFF;
byte[2] = (value >> 8) & 0xFF;
byte[3] = (value ) & 0xFF;
(即使在这里,我想你的内部代表是消极的 数字对应于协议的数字。通常是这种情况,但不是 总是。)
通常,当然,您在std::vector<char>
中构建缓冲区,
然后写&buffer[0], buffer.size()
。 (事实上你需要一个
缓冲区指针的reinterpret_cast
应该表明你的
方法是错误的。)