Serializing Eigen::Matrix using Cereal library

后端 未结 2 1932
予麋鹿
予麋鹿 2021-01-02 23:14

UPDATED: I managed to get it to work after I googled around and read the doxygen comments in code. Problem was that I missed the cast before using res

2条回答
  •  离开以前
    2021-01-02 23:59

    Your code is nearly correct but has a few mistakes:

    You don't need to be making the size_tag since you are serializing the number of rows and columns explicitly. Generally cereal uses size_tag for resizable containers like vectors or lists. Even though the matrix can resize, it makes more sense just to serialize the rows and columns explicitly.

    1. Your load function should accept its parameter by non-const reference
    2. You shouldn't use operator= with the std::ofstream objects
    3. It's better practice to let scoping and RAII handle closing/tearing down of the std::ofstream as well as cereal archives (the binary archive will flush its contents immediately, but in general cereal archives are only guaranteed to flush their contents on destruction)

    Here's a version that compiles and produces correct output under g++ and clang++:

    #include 
    #include 
    #include 
    #include 
    
    namespace cereal
    {
      template  inline
        typename std::enable_if, Archive>::value, void>::type
        save(Archive & ar, Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> const & m)
        {
          int32_t rows = m.rows();
          int32_t cols = m.cols();
          ar(rows);
          ar(cols);
          ar(binary_data(m.data(), rows * cols * sizeof(_Scalar)));
        }
    
      template  inline
        typename std::enable_if, Archive>::value, void>::type
        load(Archive & ar, Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> & m)
        {
          int32_t rows;
          int32_t cols;
          ar(rows);
          ar(cols);
    
          m.resize(rows, cols);
    
          ar(binary_data(m.data(), static_cast(rows * cols * sizeof(_Scalar))));
        }
    }
    
    int main() {
      Eigen::MatrixXd test = Eigen::MatrixXd::Random(10, 3);
    
      {
        std::ofstream out("eigen.cereal", std::ios::binary);
        cereal::BinaryOutputArchive archive_o(out);
        archive_o(test);
      }
    
      std::cout << "test:" << std::endl << test << std::endl;
    
      Eigen::MatrixXd test_loaded;
    
      {
        std::ifstream in("eigen.cereal", std::ios::binary);
        cereal::BinaryInputArchive archive_i(in);
        archive_i(test_loaded);
      }
    
      std::cout << "test loaded:" << std::endl << test_loaded << std::endl;
    }
    

提交回复
热议问题