2012-02-06 172 views
17

我想序列化我的協議緩衝區char *。這可能嗎?我知道一個可以序列化到文件按:C++谷歌協議緩衝區:序列化爲char *?

fstream output("/home/eamorr/test.bin", ios::out | ios::trunc | ios::binary); 
if (!address_book.SerializeToOstream(&output)) { 
    cerr << "Failed to write address book." << endl; 
    return -1; 
} 

但我想序列化到一個C風格的char *跨網絡傳輸。

如何做到這一點?請記住,我對C++很陌生。

回答

34

這很簡單:

size_t size = address_book.ByteSizeLong(); 
void *buffer = malloc(size); 
address_book.SerializeToArray(buffer, size); 

檢查documentation of MessageLite class也,它的父類的消息,它包含有用的方法。

+0

如何訪問此SerializeToArray函數?謝謝, – Eamorr 2012-02-06 10:27:41

+1

int size = address_book.By teSize(); void * buffer = malloc(size); address_book.SerializeToArray(buffer,size); – 2012-02-06 10:50:10

+0

嗨Evgen,有Seri​​alizeToArray被棄用或什麼?我正在使用最新版本的協議緩衝區 – Eamorr 2012-02-06 10:51:28

9

您可以將輸出端路由至ostringstream,然後使用stream.str()獲取字符串,然後使用string.c_str()訪問c字符串。

std::ostringstream stream; 
address_book.SerializeToOstream(&stream); 

string text = stream.str(); 
char* ctext = text.c_str(); 

不要忘了包括sstreamstd::ostringstream

+0

你的傳說!非常感謝您提供代碼。 – Eamorr 2012-02-06 10:22:39

+3

還有一件事 - 我沒有可用的SerializeToOstream函數 - 只是一個SerializeWithCachedSizes(...)和SerializeWithCachedSizesToArray(...);( – Eamorr 2012-02-06 10:26:57

+3

根據Google的protobuf文檔,protobuf格式是二進制的,因此可能包含null字節。我曾經在Protobuf序列化的輸出中調用c_str()的場合運行一個截斷的C字符串,因爲空字節被寫入到提供的緩衝區,並且進一步使用具有普通C風格函數的那個​​緩衝區來解釋它以一個空終止符結束 我不會推薦使用這種方法 - 坦率地說,我不認爲將protobufs序列化爲C風格的字符串是安全的,這可能是Google不提供此選項的原因 – 2015-05-08 16:33:11

3

您可以使用ByteSize來獲取消息將佔用的字節數,然後使用SerializeToArray來使用編碼消息填充數組。

0

還有一行代碼來處理序列化數據可以包含零的事實。

std::ostringstream stream; 
address_book.SerializeToOstream(&stream); 

string text = stream.str(); 
char* ctext = text.c_str(); // ptr to serialized data buffer 
// strlen(ctext) would wrongly stop at the 1st 0 it encounters. 
int data_len = text.size(); // length of serialized data