2012-07-27 13 views
7

मैं सी ++ msgpack कार्यान्वयन का उपयोग कर रहा हूं। मैंने बाइनरी डेटा को पैक करने के तरीके के बारे में एक रोडब्लॉक मारा है। एक सरणी जो वास्तव में एक छवि है करने के लिएmsgpack सी ++ कार्यान्वयन: बाइनरी डेटा कैसे पैक करें?

unsigned char* data; 

डेटा चर अंक: बाइनरी डेटा के संदर्भ में मैं निम्नलिखित प्रकार के एक बफर है। मैं क्या करना चाहता हूं यह है msgstr "msgstr" msgstr " वास्तव में बाइनरी डेटा को पैक करने का कोई उदाहरण नहीं लगता है। format specification से कच्चे बाइट समर्थित हैं, लेकिन मुझे यकीन नहीं है कि कार्यक्षमता का उपयोग कैसे करें।

मैं निम्नलिखित की तरह चरित्र संकेत का एक वेक्टर उपयोग करने की कोशिश:

msgpack::sbuffer temp_sbuffer; 
std::vector<char*> vec; 
msgpack::pack(temp_sbuffer, vec); 

लेकिन यह एक संकलक त्रुटि में परिणाम के बाद से वहाँ है टी = एसटीडी के लिए :: वेक्टर कोई समारोह टेम्पलेट।

msgpack::pack(temp_sbuffer, "Hello"); 

लेकिन यह भी एक संकलन त्रुटि में परिणाम है (यानी टी = स्थिरांक चार [6]

इस प्रकार के लिए कोई समारोह टेम्पलेट, मैं था:

मैं भी बस निम्नलिखित की कोशिश की है उम्मीद है कि कोई मुझे char सरणी के रूप में दर्शाए गए बाइनरी डेटा को पैक करने के लिए msgpack C++ का उपयोग करने के बारे में सलाह दे सकता है।

उत्तर

2

यदि आप अपनी छवि कोमें संग्रहीत कर सकते हैं

#include <iostream> 
#include <string> 
#include <vector> 
#include <msgpack.hpp> 

int main() 
{ 
    std::vector<unsigned char> data; 
    for (unsigned i = 0; i < 10; ++i) 
     data.push_back(i * 2); 

    msgpack::sbuffer sbuf; 
    msgpack::pack(sbuf, data); 

    msgpack::unpacked msg; 
    msgpack::unpack(&msg, sbuf.data(), sbuf.size()); 

    msgpack::object obj = msg.get(); 
    std::cout << obj << std::endl; 
} 

unsigned char के लिए अजीब, यह केवल काम करता है: unsigned char के एक कच्चे सरणी के बजाय, तो आप उस vector पैक कर सकते हैं। यदि आप इसके बजाय char (या यहां तक ​​कि एक व्यक्ति char) का बफर पैक करने का प्रयास करते हैं, तो यह संकलित नहीं होगा।

+0

धन्यवाद जोश

यहाँ एक कोड मूल प्रश्न के आधार पर उदाहरण है। मैंने सोचा कि मैंने पहले ही यह कोशिश की है। दुर्भाग्यवश इस समाधान के साथ मुझे बाइट एरे से अनगिनत चार के वैक्टरों तक बहुत सारे बाइनरी डेटा (छवियों) की प्रतिलिपि बनाना है। साथ ही, मुझे पूरी तरह से यकीन नहीं है कि आपका संकलन क्यों करता है। जैसा कि मुझे कोई फ़ंक्शन नहीं दिखता है जो विशेष रूप से हस्ताक्षरित चार का समर्थन करता है। मैं स्रोत कोड में गहरी खुदाई करने जा रहा हूं और देख सकता हूं कि यह एक और अधिक प्रभावी तरीका है जिसे मैं कर सकता हूं (यानी प्रतिलिपि से परहेज करना)। – mdb841

+0

इसके अलावा, यह इसे बाइनरी डेटा के बजाए वर्णों की एक सरणी के रूप में सहेज लेगा, जो कार्यान्वयन के अनुसार एक अलग प्रकार है ... –

+1

बस इसे देखा: वेक्टर के बजाय वेक्टर का उपयोग करना प्रतीत होता है सरणी के बजाय बाइनरी प्रकार ... –

4

जोश provided a good answer लेकिन इसके लिए बाइट बफर को चार के वेक्टर में कॉपी करने की आवश्यकता है। मैं प्रतिलिपि को कम करने और बफर का उपयोग सीधे (यदि संभव हो) का उपयोग करता हूं। निम्नलिखित एक वैकल्पिक समाधान है:

स्रोत कोड के माध्यम से देख रहे हैं और यह निर्धारित करने की कोशिश कर रहा है कि msgpack::packer<>::pack_raw(size_t l) और msgpack::packer<>::pack_raw_body(const char* b, size_t l) पर विनिर्देश के अनुसार अलग-अलग डेटा प्रकार पैक किए गए हैं। हालांकि इन विधियों के लिए कोई प्रलेखन प्रतीत नहीं होता है, इस तरह मैं उन्हें वर्णित करता हूं।

  1. msgpack :: पैकर <> :: pack_raw (size_t एल): यह विधि प्रकार पहचान संलग्न कर देता है बफ़र होना (यानी ठीक कच्चे, raw16 या raw32) और साथ ही आकार जानकारी (जो एक तर्क है विधि के लिए)।
  2. msgpack :: पैकर <> :: pack_raw_body (const char * b, size_t l): यह विधि कच्चे डेटा को बफर में जोड़ती है।

निम्नलिखित कैसे एक चरित्र सरणी पैक करने के लिए की एक सरल उदाहरण है:

msgpack::sbuffer temp_sbuffer; 
msgpack::packer<msgpack::sbuffer> packer(&temp_sbuffer); 
packer.pack_raw(5); // Indicate that you are packing 5 raw bytes 
packer.pack_raw_body("Hello", 5); // Pack the 5 bytes 

ऊपर के उदाहरण किसी भी बाइनरी डेटा पैक करने के लिए बढ़ाया जा सकता है। यह किसी को इंटरमीडिएट (यानी चार का वेक्टर) प्रतिलिपि किए बिना बाइट एरे/बफर से सीधे पैक करने की अनुमति देता है।

#include "msgpack.hpp" 

class myClass 
{ 
public: 
    msgpack::type::raw_ref r; 
    MSGPACK_DEFINE(r); 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    const char* str = "hello"; 

    myClass c; 

    c.r.ptr = str; 
    c.r.size = 6; 

    // From here on down its just the standard MessagePack example... 

    msgpack::sbuffer sbuf; 
    msgpack::pack(sbuf, c); 

    msgpack::unpacked msg; 
    msgpack::unpack(&msg, sbuf.data(), sbuf.size()); 

    msgpack::object o = msg.get(); 

    myClass d; 
    o.convert(&d); 

    OutputDebugStringA(d.r.ptr); 

    return 0; 

} 

अस्वीकरण::

+0

संबंधित अनपॅकिंग कैसा दिखता है? –

3

MessagePack जो तुम इतनी तरह इस्तेमाल कर सकते हैं एक raw_ref प्रकार है मैं, नहीं कच्चे बाइट्स serialising पर न के बराबर प्रलेखन पढ़ने के माध्यम से हेडर फाइल के आसपास poking द्वारा इस पाया, तो यह हो सकता है कि 'सही' तरीका न हो (हालांकि यह था जिसे अन्य सभी 'मानक' प्रकारों के साथ परिभाषित किया गया था, जो एक धारावाहिक स्पष्ट रूप से संभालना चाहते हैं)।

+0

मैंने अभी पुष्टि की है कि यह मेरे लिए काम करता है, कम से कम एन्कोडिंग पर। मैं एक std :: वेक्टर पॉप्युलेट करता हूं, वेक्टर में raw_ref इंगित करता हूं, और raw_ref पैक करता हूं। परिणाम msgpack प्रकार कोड C4 का उपयोग करता है, जो "बिन 8" प्रारूप के लिए आईडी है। – mjwach

+1

अनपॅकिंग पर, इस पर एक पकड़ है: लाइब्रेरी एक चरित्र धारा को कच्चे_रेफ़ में पर्याप्त रूप से अनपैक कर देगी, लेकिन फिर यह स्पष्ट नहीं है, एक अज्ञानी पर्यवेक्षक को, कच्चे_ref द्वारा दी गई स्मृति का क्या मालिक है। मेरा आकस्मिक विश्लेषण बताता है कि यह msgpack :: अनपॅक संरचना है; यदि यह सही है तो मुझे लगता है कि जब तक अनपॅक किए गए raw_ref को पढ़ने की आवश्यकता हो, तब तक किसी को अनपॅकिंग के बाद उस संरचना को रखना चाहिए। ... लेकिन शायद यह अन्य अनपॅक किए गए प्रकारों के लिए भी सच है? मुझे यकीन नहीं है। इस पुस्तकालय में वास्तव में बेहतर दस्तावेज़ीकरण की आवश्यकता है। :( – mjwach

0

msgpack-c को प्रश्न और उत्तर पोस्ट करने के बाद अद्यतन किया गया है। मैं वर्तमान स्थिति को सूचित करना चाहता हूं।

चूंकि msgpack-c संस्करण 2.0.0 सी-शैली सरणी समर्थित है। देखें https://github.com/msgpack/msgpack-c/releases

msgpack-c कॉन्स्ट चार सरणी जैसे "हैलो" पैक कर सकता है। प्रकार रूपांतरण नियम https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#predefined-adaptors दस्तावेज किया गया है।

चार सरणी एसटीआर में मैप की गई है। यदि आप एसटीआर के बजाय बीआईएन का उपयोग करना चाहते हैं, तो आपको msgpack::type::raw_ref के साथ लपेटने की आवश्यकता है। वह अवलोकन पैकिंग है।

यहाँ खोल और विवरण परिवर्तित कर रहे हैं: https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_object#conversion

अनपैक MessagePack स्वरूपित बाइट धारा से msgpack::object बनाने का मतलब है। कनवर्ट का मतलब है msgpack::object से सी ++ ऑब्जेक्ट में कनवर्ट करना।

यदि संदेशपैक स्वरूपित डेटा एसटीआर है, और गुप्त लक्ष्य प्रकार चार सरणी है, सरणी में डेटा कॉपी करें, और यदि सरणी में अतिरिक्त क्षमता है, तो '\ 0' जोड़ें। यदि संदेशपैक स्वरूपित डेटा बीआईएन है, तो '\ 0' जोड़ा नहीं गया है।

#include <msgpack.hpp> 
#include <iostream> 

inline 
std::ostream& hex_dump(std::ostream& o, char const* p, std::size_t size) { 
    o << std::hex << std::setw(2) << std::setfill('0'); 
    while(size--) o << (static_cast<int>(*p++) & 0xff) << ' '; 
    return o; 
} 

int main() { 
    { 
     msgpack::sbuffer temp_sbuffer; 
     // since 2.0.0 char[] is supported. 
     // See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#predefined-adaptors 
     msgpack::pack(temp_sbuffer, "hello"); 
     hex_dump(std::cout, temp_sbuffer.data(), temp_sbuffer.size()) << std::endl; 

     // packed as STR See https://github.com/msgpack/msgpack/blob/master/spec.md 
     // '\0' is not packed 
     auto oh = msgpack::unpack(temp_sbuffer.data(), temp_sbuffer.size()); 
     static_assert(sizeof("hello") == 6, ""); 
     char converted[6]; 
     converted[5] = 'x'; // to check overwriting, put NOT '\0'. 
     // '\0' is automatically added if char-array has enought size and MessagePack format is STR 
     oh.get().convert(converted); 
     std::cout << converted << std::endl; 
    } 
    { 
     msgpack::sbuffer temp_sbuffer; 
     // since 2.0.0 char[] is supported. 
     // See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#predefined-adaptors 
     // packed as BIN 
     msgpack::pack(temp_sbuffer, msgpack::type::raw_ref("hello", 5)); 
     hex_dump(std::cout, temp_sbuffer.data(), temp_sbuffer.size()) << std::endl; 

     auto oh = msgpack::unpack(temp_sbuffer.data(), temp_sbuffer.size()); 
     static_assert(sizeof("hello") == 6, ""); 
     char converted[7]; 
     converted[5] = 'x'; 
     converted[6] = '\0'; 
     // only first 5 bytes are written if MessagePack format is BIN 
     oh.get().convert(converted); 
     std::cout << converted << std::endl; 
    } 
} 

रनिंग डेमो:: https://wandbox.org/permlink/mYJyYycfsQIwsekY

संबंधित मुद्दे