在C中我习惯使用char *来映射表示网络数据包的一些结构。然后我只需分配数据包参数并通过网络发送:
更新 - 我忘记添加我有一些有效负载
struct packet {
uint64_t id __attribute__((packed));
uint64_t something __attribute__((packed));
short flags __attribute__((packed));
// here follows payload with variable length
};
...
char *payload = get_payload();
size_t payload_size = get_payload_size();//doesnt matter how
char *data = malloc(sizeof(struct packet)+payload_size);
struct packet *pkt = (struct packet *)data;
pkt->id = 123;
pkt->something = get_something();
pkt->flags = FLAG | FLAG2;
memcpy(data+sizeof(struct packet), payload, payload_size);
send(data, sizeof(struct packet)+payload_size);
现在我想用一些不错的C ++特性来实现它(如果有更好的方法可以做到这一点) 我在C ++中可以做的最好的改变是使用new而不是malloc。
char *data = new char[sizeof(struct packet)];//rest is same
好吧这就是所谓的对象序列化..我发现有几个例子总是使用boost我无法使用..在C ++中是不是有一种本地方式来实现这个?
答案 0 :(得分:2)
没有理由创建char*
和pkt*
。您可以创建并发送一个对象,如:
packet pkt; // create automatic object
pkt.id = 123;
pkt.something = get_something();
pktflags = FLAG | FLAG2;
// here we cast the address of pkt to a char* so we can send it
send(reinterpret_cast<char*>(&pkt), sizeof(packet));
编辑:
由于问题已更新为将有效负载添加到struct
数据的末尾,因此您必须使用与在C中执行的方法相同的方法。当new
向上指针时语法是
char * data = new char[sizeof(packet) + payload_size];
在C中使用struct
时,C ++中不需要struct
关键字。您可以按名称使用它。
答案 1 :(得分:1)
我不喜欢原始代码依赖于非标准扩展程序__attribute__((packed))
的方式。由于没有标准方法要求struct
根本没有填充,因此将结构复制到缓冲区的唯一标准兼容方法是单独复制每个成员。
这激发了我编写一个c ++ 11帮助程序来将可变数量的变量复制到char
数组中。并帮助使用它,帮助计算这些变量的总大小(已经完成here)。使用这些帮助程序,您可以轻松地将struct
的成员复制到缓冲区中,而无需打包struct
。
// variadic sizeof
// mostly same as https://stackoverflow.com/a/12666815/2079303
constexpr std::size_t sizeof_all() {
return 0;
}
template <typename Head, typename... Tail>
constexpr std::size_t sizeof_all(const Head& head, const Tail&... tail) {
return sizeof head + sizeof_all(tail...);
}
// variadic memcpy
void memcpy_all(char*) {}
template <typename Head, typename... Tail>
void memcpy_all(char* out, const Head& head, const Tail&... tail) {
auto offset = sizeof head;
std::memcpy(out, &head, offset);
memcpy_all(out + offset, tail...);
}
// to use
packet p;
std::size_t buffer_size = sizeof_all(p.id, p.something, p.flags) + payload_size;
char* data = new char[buffer_size];
memcpy_all(data, p.id, p.something, p.flags);
现在,您只需关注字节序。