2016-12-02 6 views
0

Я новичок в messagepack, и я пытаюсь взять хэш в perl, сериализую его, используя messagepack, записываю его в файл, передаю его в код C++, где файл читается и десериализуется в карту.MessagePack Perl to C++ deserialisation

Мой Perl-код для создания файла есть (примечание - я добавил дополнительную часть, чтобы проверить, я мог прочитать файл обратно и десериализации правильно в Perl, хотя я на самом деле не нужно делать):

#! perl 

use strict; 
use warnings; 

use Data::MessagePack; 

my %hTestHash = ('AAAAAA' => '20020101', 
       'BBBBBB' => '20030907'); 

my $packed = Data::MessagePack->pack(\%hTestHash); 

open my $fh, '>', 'splodge.bin' or die "Failed to open slodge.bin for write: $!"; 
print $fh $packed; 
close $fh; 

open my $fh2, '<', 'splodge.bin' or die "Failed to open slodge.bin for read: $!"; 
local $/; 
my $file = <$fh2>; 

my $hrTest = Data::MessagePack->unpack($file); 

Мой с ++ код десериализации затем:

#include "msgpack.hpp" 
#include <string> 
#include <iostream> 
#include <sstream> 
#include <fstream> 

int main(void) 
{ 
    // Deserialize the serialized data. 
    std::ifstream ifs("splodge.bin", std::ifstream::in); 
    std::stringstream buffer; 
    buffer << ifs.rdbuf(); 
    msgpack::unpacked upd; 
    msgpack::unpack(&upd, buffer.str().data(), buffer.str().size()); 
    msgpack::object obj = upd.get(); 
    std::map<std::string, std::string> output_map; 
    msgpack::convert(output_map, obj); 

    string date = output_map.at("AAAAAA"); 

    return 0; 
} 

Это создает карту 2 элемента в output_map, но он содержит только значения для мусора - моя программа вылетает на output_map.at() с

{"▒▒▒▒▒▒"=>"▒▒▒▒▒▒▒▒", "▒▒▒▒▒▒"=>"▒▒▒▒▒▒▒▒"} 
terminate called after throwing an instance of 'std::out_of_range' 
    what(): map::at 
Aborted 

Мне не удалось найти примеры этого конкретного случая использования и изо всех сил пытаться понять, что случилось - это проблема в конце сериализации или (кажется, скорее) в конце десериализации?

EDIT: Спасибо @ SinanÜnür за указание моей ошибки, которую я сейчас обновил в вопросе. Это не меняет того факта, что хеш заполняется значениями мусора, поэтому одно и то же исключение выбрасывается независимо от того, какой поиск выполняется.

+0

@ SinanÜnür спасибо , см. мое редактирование выше – rbennett485

+0

@ SinanÜnür, так что этот же код работает правильно для вас и создает карту в C++? – rbennett485

+0

''> '' и '' <''должны быть' '>: raw'' и' '<: raw'', особенно если вы находитесь на машине под Windows. Аналогично, программа C++ должна установить поток в двоичный. – ikegami

ответ

-2

Наконец-то удалось заставить его работать с комбинацией правильного считывания двоичного файла и некоторого вмешательства со странными собственными типами данных, которые у нас есть.

Функционирование код (который десериализует структуру в Map<string, msgpack::object>, что требует дополнительного шага десериализации каждого значения, когда это необходимо) является:

#include "msgpack.hpp" 
#include "map.h" 
#include <string> 
#include <iostream> 
#include <fstream> 

void unpack_map(const msgpack::object& o, Map<string,msgpack::object>& results){ 
    ASSERT(o.type == msgpack::type::MAP); 
    for (msgpack::object_kv *p = o.via.map.ptr, *pend = (o.via.map.ptr + o.via.map.size); p != pend; ++p) 
    results[p->key.as<string>()] = p->val; 
} 

int main(void) 
{ 
    streampos size; 
    char * memblock; 

    ifstream file ("splodge.bin", ios::in|ios::binary|ios::ate); 
    if (file.is_open()) 
    { 
     size = file.tellg(); 
     memblock = new char [size]; 
     file.seekg (0, ios::beg); 
     file.read (memblock, size); 
     file.close(); 

     cout << "the entire file content is in memory"; 
    } 
    else cout << "Unable to open file"; 

    msgpack::unpacked upd; 
    msgpack::unpack(&upd, memblock, size); 
    msgpack::object obj = upd.get(); 

    if(obj.type != msgpack::type::MAP) { 
    cout << ":(" << endl; 
    } else { 
    cout << ":)" << endl; 
    } 
    cout << "size: " << obj.via.map.size << endl; 

    Map<string, msgpack::object> objectMap; 
    unpack_map(obj, objectMap); 

    msgpack::object val = objectMap["BBBBBB"]; 
    string tmp = string(val.via.raw.ptr, val.via.raw.size); 

    delete[] memblock; 
    return 0; 
} 

где tmp принимает значение 20030907