C++ 如何在C++;?
我有一个小的对象层次结构,需要通过套接字连接进行序列化和传输。我需要序列化对象,然后根据对象的类型对其进行反序列化。在C++中有没有一种简单的方法来实现这一点(就像java中的那样)? <是否有任何C++序列化的在线代码示例或教程?< /P>C++ 如何在C++;?,c++,serialization,marshalling,c++-faq,C++,Serialization,Marshalling,C++ Faq,我有一个小的对象层次结构,需要通过套接字连接进行序列化和传输。我需要序列化对象,然后根据对象的类型对其进行反序列化。在C++中有没有一种简单的方法来实现这一点(就像java中的那样)? 编辑:我只是想澄清一下,我正在寻找将对象转换为字节数组,然后再转换回对象的方法。我可以处理套接字传输。谈到序列化,我想到了。至于通过网络传输序列化数据,我会使用Berkeley套接字或 编辑: 如果要将对象序列化为字节数组,可以通过以下方式使用boost序列化程序(摘自教程站点): #包括 #包括 类gps_位
编辑:我只是想澄清一下,我正在寻找将对象转换为字节数组,然后再转换回对象的方法。我可以处理套接字传输。谈到序列化,我想到了。至于通过网络传输序列化数据,我会使用Berkeley套接字或 编辑:
如果要将对象序列化为字节数组,可以通过以下方式使用boost序列化程序(摘自教程站点):
#包括
#包括
类gps_位置
{
私人:
好友类boost::serialization::access;
模板
无效序列化(存档和ar,常量未签名整数版本)
{
ar&学位;
应收账款&分钟;
ar&秒;
}
国际学位;
整数分钟;
浮动秒;
公众:
gps_位置(){};
gps_位置(整数d、整数m、浮点s):
度(d)、分(m)、秒(s)
{}
};
因此,实际的序列化非常简单:
#include <fstream>
std::ofstream ofs("filename.dat", std::ios::binary);
// create class instance
const gps_position g(35, 59, 24.567f);
// save data to archive
{
boost::archive::binary_oarchive oa(ofs);
// write class instance to archive
oa << g;
// archive and stream closed when destructors are called
}
#包括
ofs流的std::of(“filename.dat”,std::ios::binary);
//创建类实例
常数gps_位置g(35,59,24.567f);
//将数据保存到存档
{
boost::archive::二进制文件oa(ofs);
//将类实例写入存档
oa在某些情况下,处理简单类型时,您可以执行以下操作:
object o;
socket.write(&o, sizeof(o));
这可以作为概念证明或初稿,这样团队的其他成员就可以继续处理其他部分
但是迟早,通常是更早,这会让你受伤!
您遇到以下问题:
- 虚拟指针表将被损坏
- 指针(指向数据/成员/函数)将损坏
- 不同机器上的填充/对齐差异
- 大/小端字节排序问题
- 浮动/双精度的实现变化
(此外,您还需要知道您在接收端要拆包的内容。)
您可以通过为每个类开发自己的编组/解编组方法来改进这一点。(理想情况下是虚拟的,因此它们可以在子类中扩展。)几个简单的宏将允许您以大端/小端中立顺序快速写出不同的基本类型
但是这种繁重的工作更好,也更容易通过处理。有一种通用模式可用于序列化对象。基本原语是可以从迭代器读取和写入的两个函数:
template <class OutputCharIterator>
void putByte(char byte, OutputCharIterator &&it)
{
*it = byte;
++it;
}
template <class InputCharIterator>
char getByte(InputCharIterator &&it, InputCharIterator &&end)
{
if (it == end)
{
throw std::runtime_error{"Unexpected end of stream."};
}
char byte = *it;
++it;
return byte;
}
从little endian顺序反序列化:
data.push_back(integer32 & 0xFF);
data.push_back((integer32 >> 8) & 0xFF);
data.push_back((integer32 >> 16) & 0xFF);
data.push_back((integer32 >> 24) & 0xFF);
integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
反序列化是向后进行的。请注意体系结构的字节顺序
序列化字符串
首先,您需要就编码达成一致。UTF-8是常见的。然后,以长度前缀的方式存储它:首先,使用上面提到的方法存储字符串的长度,然后逐字节写入字符串
序列化数组。
它们与字符串相同。首先序列化表示数组大小的整数,然后序列化其中的每个对象
序列化整个对象
正如我之前所说的,他们应该有一个序列化
方法,将内容添加到向量中。
要取消序列化一个对象,它应该有一个接受字节流的构造函数。它可以是istream
,但在最简单的情况下,它可以只是一个引用uint8\t
指针。构造函数从流中读取它想要的字节,并在对象中设置字段。
如果系统设计良好并按对象字段顺序序列化字段,则可以将流以初始值设定项列表的形式传递给字段的构造函数,并按正确的顺序反序列化它们
序列化对象图
首先,您需要确保这些对象是否确实是您想要序列化的对象。如果目标上存在这些对象的实例,则不需要序列化它们
现在您发现需要序列化指针指向的对象。
指针的问题在于,它们仅在使用它们的程序中有效。无法序列化指针,应停止在对象中使用它们。而应创建对象池。
这个对象池基本上是一个包含“盒子”的动态数组。这些框有一个引用计数。非零引用计数表示活动对象,零表示空插槽。然后创建类似于共享\u ptr的智能指针,该指针不存储指向该对象的指针,而是存储数组中的索引。您还需要就表示空指针的索引达成一致,例如-1
我们在这里所做的基本上是用数组索引替换指针。
现在序列化时,您可以像往常一样序列化此数组索引。您不必担心对象将在目标系统的内存中的位置。只需确保它们也具有相同的对象池
所以我们需要序列化对象池。但是哪些对象池呢?当你序列化一个对象图时,你不仅仅是序列化一个对象,而是序列化整个系统。这意味着系统的序列化不应该从系统的一部分开始。那些对象不应该担心系统的其余部分,它们只需要序列化你应该有一个系统序列化程序例程来协调系统的序列化,遍历相关的对象池并序列化所有的对象池
在接收端,对象所在的所有数组都被反序列化,从而重新创建所需的对象图
序列化函数指针
不要在对象中存储指针。创建一个静态数组,其中包含指向这些函数的指针,并存储
class Foo
{
int internal1, internal2;
// So it can be found using ADL and it accesses private parts.
template <class OutputCharIterator>
friend void serialize(const Foo &obj, OutputCharIterator &&it)
{
// Call putByte or other serialize overloads.
}
// Deserialize similar.
};
std::ofstream file("savestate.bin");
serialize(yourObject, std::ostreambuf_iterator<char>(file));
std::ifstream file("savestate.bin");
deserialize(yourObject, std::istreamBuf_iterator<char>(file), std::istreamBuf_iterator<char>());
data.push_back(integer32 & 0xFF);
data.push_back((integer32 >> 8) & 0xFF);
data.push_back((integer32 >> 16) & 0xFF);
data.push_back((integer32 >> 24) & 0xFF);
integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
uint8_t mem[8];
memcpy(mem, doubleValue, 8);
data.push_back(mem[0]);
data.push_back(mem[1]);
...
#include "c_plus_plus_serializer.h"
static void serialize (std::ofstream out)
{
char a = 42;
unsigned short b = 65535;
int c = 123456;
float d = std::numeric_limits<float>::max();
double e = std::numeric_limits<double>::max();
std::string f("hello");
out << bits(a) << bits(b) << bits(c) << bits(d);
out << bits(e) << bits(f);
}
static void deserialize (std::ifstream in)
{
char a;
unsigned short b;
int c;
float d;
double e;
std::string f;
in >> bits(a) >> bits(b) >> bits(c) >> bits(d);
in >> bits(e) >> bits(f);
}