2015-12-11 19 views
0

在C中,我曾用char *來處理表示網絡數據包的一些結構。然後,我只是分配數據包的參數,並通過網絡發送:如何在C++中將結構映射爲字符合適的方法

修訂 - 我忘了補充一點,我有一些有效載荷

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 

確定這被稱爲對象的序列化。我已經找到了幾個例子總是使用升壓,我不能用..心不是有原生的方式在C++來acomplish呢?

+1

你在問什麼一般稱爲「對象序列化」。嘗試使用Google搜索或選擇「C++對象序列化」。 – piokuc

回答

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了指針使用struct像C.你只可以按名稱使用它時,語法將

char * data = new char[sizeof(packet) + payload_size]; 

也是用C不需要struct關鍵字++。

+0

謝謝,我喜歡你的解決方案,但我忘了補充說,我正在使用有效載荷後的數據包..抱歉改變問題。將「reinterpret_cast方式」工作,如果數據包將包含例如char *的有效載荷? – nayana

+0

@otopolsky我已經更新了我的答案。 – NathanOliver

0

我不喜歡你原來的代碼依賴於非標準的擴展__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); 

現在,你只需要關心自己的字節順序。