如何在C ++中将结构映射到char适当的方法

时间:2015-12-11 15:49:41

标签: c++ networking struct

在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 ++中是不是有一种本地方式来实现这个?

2 个答案:

答案 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);

现在,您只需关注字节序。