使用Cereal对结构的静态数组进行C ++序列化

时间:2017-11-30 13:35:46

标签: c++ arrays serialization

我正在使用Cereal库来序列化结构化数据,通过MPI发送它们,然后使用CUDA在GPU上处理它们。由于后者,我不能使用std :: vector,因为CUDA在动态对象方面存在问题。因此我使用静态结构数组。

目标

做二进制序列化&对具有嵌套静态对象数组的对象进行反序列化。

要进行SERIALIZED的对象

//==========================================================//
//                  ELEMENT DEFINITION                      //
//==========================================================//
class element{
public:
    //==========================//
    //          CONTENT         //
    //==========================//
    int grid_id;
    int NN_id;
    int debug;

    //==========================//
    //      SERIALIZATION       //
    //==========================//
    // function required by cereal library
    template<class Archive>
    void serialize(Archive & ar){
        ar( grid_id );
        ar( NN_id );
        ar( debug );
    }
};

//==========================================================//
//                      CONTAINER DEFINITION                //
//==========================================================//
class GPU_in_grid : public Managed{
public:
    //==========================//
    //          CONTENT         //
    //==========================//
    int gpu_id;
    element element[GRID_SIZE];        <------ static array of structures
    int debug;


    //==========================//
    //      SERIALIZATION       //
    //==========================//
    template<class Archive>
    void serialize(Archive & ar){
        ar( gpu_id );
        ar( debug );
        ar( element );

    }
};

序列化功能

// cereal serialization
#include <cereal/archives/binary.hpp>
#include <cereal/archives/portable_binary.hpp>
//#include <cereal/archives/xml.hpp>

template<typename data_type>
int Process::serialize(data_type * data, char *serial_data, int *size){
    // serialize the data
    std::ostringstream oss(std::ios::binary);
    cereal::BinaryOutputArchive ar(oss);
    //cereal::XMLOutputArchive ar(std::cout);
    ar(*data);
    std::string s=oss.str();
    *size = s.length();
    strncpy(serial_data, s.c_str(), s.length());
    std::cout << "buffer["<< s.length() << "] >> " << s << std::endl;
    s.clear();
    return _SUCCESS_;
};

template<typename data_type>
int Process::deserialize(data_type * data, char *serial_data, int size){
    // create temporary buffer to store the received data
    char * buf=new char[size];
    strncpy(buf, serial_data, size);
    std::istringstream iss(std::string(serial_data, size), std::ios::binary);
    cereal::BinaryInputArchive arin(iss);
    arin(*data);
    // clean buffer
    delete[] buf;
    return _SUCCESS_;
};

调试输出

cpu_mem BEFORE serialization
    cpu_mem.debug = -1
    cpu_mem.gpu_id = -5
    cpu_mem.element[0].NN_id = 1  
    cpu_mem.element[0].debug = 2  
buffer[248] >> ��������           <------ binary format
cpu_mem AFTER deserialization
    cpu_mem.debug = -1            <----- CORRECT
    cpu_mem.gpu_id = -5           <----- CORRECT
    cpu_mem.element[0].NN_id = 0  <----- INCORRECT
    cpu_mem.element[0].debug = 0  <----- INCORRECT

如果我对流进行一些操作,我可以将序列化对象打印为XML,以检查序列化是否成功。

<?xml version="1.0" encoding="utf-8"?>
<cereal>
    <value0>
        <gpu_id>-5</gpu_id>               <----- CORRECT
        <debug>-1</debug>                 <----- CORRECT
        <element>
            <value0>
                <grid_id>0</grid_id>
                <NN_id>1</NN_id>          <----- CORRECT
                <debug>2</debug>          <----- CORRECT
            </value0>
            <value1>
                <grid_id>32522</grid_id>
                <NN_id>2</NN_id>
                <debug>4612412</debug>
            </value1>
        </element>
    </value0>
</cereal>

问题

上面的输出显示,反序列化正确识别容器中的变量(类GPU_in_grid)但不能反序列化我的结构的较低级别,即静态结构数组 - &gt;元素[]。

1 个答案:

答案 0 :(得分:1)

由于某些未知原因,strncpy()出现故障。字符串的内容与数组的内容不同,即使我关注&#39; \ 0&#39;,这需要附加在char数组的末尾,如http://www.cplusplus.com/reference/string/string/copy/所示。

我最终使用了std :: string.copy(),只要你添加&#39; \ 0&#39;在char数组的末尾。

上面的代码就可以了。