C++ 结构体的序列化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16543519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Serialization of struct
提问by Vigo
Suppose i have a struct whose member values i want to send over the network to another system using winsock 2. I'm using C++ language. How do i convert it to char * keeping in mind that the struct has to be serialized before sending and also how do i deserialize the char * into struct at the other end? I found boost serialization as a suggestion to similar question but can anyone illustrate with a small code snippet for both serialization and deserialization ?
假设我有一个结构,我想使用 winsock 2 通过网络将其成员值发送到另一个系统。我使用的是 C++ 语言。我如何将它转换为 char * 记住结构必须在发送之前序列化,以及如何将 char * 反序列化为另一端的结构?我发现 boost 序列化是对类似问题的建议,但谁能用一个小代码片段来说明序列化和反序列化?
This question might seem very basic but the other answers to the related posts did not help much.
这个问题可能看起来很基本,但相关帖子的其他答案并没有多大帮助。
回答by Amith Chinthaka
Following example shows a simplest way to serialize struct
into char
array and de-serialize it.
以下示例显示了序列化最简单的方式struct
进入char
阵列和反序列化。
#include <iostream>
#include <cstring>
#define BUFSIZE 512
#define PACKETSIZE sizeof(MSG)
using namespace std;
typedef struct MSG
{
int type;
int priority;
int sender;
char message[BUFSIZE];
}MSG;
void serialize(MSG* msgPacket, char *data);
void deserialize(char *data, MSG* msgPacket);
void printMsg(MSG* msgPacket);
int main()
{
MSG* newMsg = new MSG;
newMsg->type = 1;
newMsg->priority = 9;
newMsg->sender = 2;
strcpy(newMsg->message, "hello from serverstruct MyStruct {
int data;
char* someNullTerminatedName; // Assuming not larger than 1023 chars
std::ostream& serialize(std::ostream& os) const {
char null = 'MyStruct foo, bar;
std::stringstream stream;
foo.serialize(stream);
// ... Now stream.str().c_str() contains a char* buffer representation of foo.
// For example it might contain [ 1f 3a 4d 10 h e l l o w o r l d int main() {
// create and open a character archive for output
// we simply use std::strinstream here
std::stringstream ofs;
// create class instance
const gps_position g(35, 59, 24.567f);
// save data to archive
{
boost::archive::text_oarchive oa(ofs);
// write class instance to archive
oa << g;
// archive and stream closed when destructors are called
}
// now we have const char* ofs.str().c_str()
// transfer those bytes via network
// read them on the other machine
gps_position newg;
{
// create and open an archive for input
std::stringstream ifs(the_string_we_read_from_the_network);
boost::archive::text_iarchive ia(ifs);
// read class state from archive
ia >> newg;
// archive and stream closed when destructors are called
}
return 0;
}
]
bar.deserialize(stream);
// ... Now bar is a copy, via a serial stream of data, of foo.
';
os.write((char*)&data, sizeof(data));
os.write(someNullTerminatedName, strlen(someNullTerminatedName));
os.write(&null, 1);
return os;
}
std::istream& deserialize(std::istream& is) {
char buffer[1024];
int i = 0;
is.read((char*)&data, sizeof(data));
do { buffer[i] = is.get(); ++i; } while(buffer[i] != '##代码##');
if (someNullTerminatedName != NULL) free(someNullTerminatedName);
someNullTerminatedName = (char*)malloc(i);
for (i = 0; buffer[i] != '##代码##'; ++i) {
someNullTerminatedName[i] = buffer[i];
}
return is;
}
};
");
printMsg(newMsg);
char data[PACKETSIZE];
serialize(newMsg, data);
MSG* temp = new MSG;
deserialize(data, temp);
printMsg(temp);
return 0;
}
void serialize(MSG* msgPacket, char *data)
{
int *q = (int*)data;
*q = msgPacket->type; q++;
*q = msgPacket->priority; q++;
*q = msgPacket->sender; q++;
char *p = (char*)q;
int i = 0;
while (i < BUFSIZE)
{
*p = msgPacket->message[i];
p++;
i++;
}
}
void deserialize(char *data, MSG* msgPacket)
{
int *q = (int*)data;
msgPacket->type = *q; q++;
msgPacket->priority = *q; q++;
msgPacket->sender = *q; q++;
char *p = (char*)q;
int i = 0;
while (i < BUFSIZE)
{
msgPacket->message[i] = *p;
p++;
i++;
}
}
void printMsg(MSG* msgPacket)
{
cout << msgPacket->type << endl;
cout << msgPacket->priority << endl;
cout << msgPacket->sender << endl;
cout << msgPacket->message << endl;
}
回答by rwols
You can just do
你可以做
##代码##It's up to you to take care of endianness and differences in size of int
s and whatnot.
由您来处理字节序和int
s大小的差异等等。
Example:
例子:
##代码##If you have a socket library that exposes its interface via C++ iostreams then you don't even need the stringstream.
如果您有一个通过 C++ iostreams 公开其接口的套接字库,那么您甚至不需要 stringstream。
回答by Nick
You can also have a look at Protocol Buffersfrom Google which is a platform/language independent library for sending data between hosts.
您还可以查看Google 的Protocol Buffers,它是一个独立于平台/语言的库,用于在主机之间发送数据。
However, the paradigm is shifted towards writing the protocol first and then fitting your data structures into it. The advantage of this though is that it forces your software architecture to fit well with simple data types.
然而,范式转向首先编写协议,然后将您的数据结构放入其中。这样做的好处是它迫使你的软件架构很好地适应简单的数据类型。
回答by mkaes
Ok I will take the examplefrom the boost web site as I don't understand what you can not understand from it.
I added some comments and changes to it how you can transfer via network. The network code itself is not in here. For this you can take a look at boost::asio.
好的,我将从boost 网站上举个例子,因为我不明白你不能从中理解什么。
我添加了一些评论和更改,如何通过网络传输。网络代码本身不在这里。为此,您可以查看boost::asio。
回答by Arthur
If your struct is POD
you can use memcpy
:
如果你的结构是POD
你可以使用memcpy
:
::memcpy(data, &your_struct, sizeof(YourStruct)));
::memcpy(data, &your_struct, sizeof(YourStruct)));
and vice versa at reception:
反之亦然:
::memcpy(&your_struct, data, sizeof(YourStruct)));
::memcpy(&your_struct, data, sizeof(YourStruct)));
Where data
is a char*
. Don't forget you have to Allocate it, making sure it's big enought and delete it at the end.
哪里data
有char*
. 不要忘记你必须分配它,确保它足够大并在最后删除它。