c++ - Serializing Eigen::Matrix using Cereal library -


updated: managed work after googled around , read doxygen comments in code. problem missed cast before using resize() method , not using std::ios::binary streams. if want similar, better check answer azoth.

i trying serialize eigen::matrix type using cereal. have (loosely based on https://gist.github.com/mtao/5798888 , the types in cereal/types):

#include <cereal/cereal.hpp> #include <cereal/archives/binary.hpp> #include <eigen/dense> #include <fstream>  namespace cereal {     template <class archive, class _scalar, int _rows, int _cols, int _options, int _maxrows, int _maxcols> inline         typename std::enable_if<traits::is_output_serializable<binarydata<_scalar>, archive>::value, void>::type         save(archive & ar, eigen::matrix<_scalar, _rows, _cols, _options, _maxrows, _maxcols> const & m)     {             int rows = m.rows();             int cols = m.cols();             ar(make_size_tag(static_cast<size_type>(rows * cols)));             ar(rows);             ar(cols);             ar(binary_data(m.data(), rows * cols * sizeof(_scalar)));         }      template <class archive, class _scalar, int _rows, int _cols, int _options, int _maxrows, int _maxcols> inline         typename std::enable_if<traits::is_input_serializable<binarydata<_scalar>, archive>::value, void>::type         load(archive & ar, eigen::matrix<_scalar, _rows, _cols, _options, _maxrows, _maxcols> const & m)     {             size_type size;             ar(make_size_tag(size));              int rows;             int cols;             ar(rows);             ar(cols);              const_cast<eigen::matrix<_scalar, _rows, _cols, _options, _maxrows, _maxcols> &>(m).resize(rows, cols);              ar(binary_data(const_cast<_scalar *>(m.data()), static_cast<std::size_t>(size * sizeof(_scalar))));         } }  int main() {     eigen::matrixxd test = eigen::matrixxd::random(10, 3);     std::ofstream out = std::ofstream("eigen.cereal", std::ios::binary);     cereal::binaryoutputarchive archive_o(out);     archive_o(test);      std::cout << "test:" << std::endl << test << std::endl;      out.close();      eigen::matrixxd test_loaded;     std::ifstream in = std::ifstream("eigen.cereal", std::ios::binary);     cereal::binaryinputarchive archive_i(in);     archive_i(test_loaded);      std::cout << "test loaded:" << std::endl << test_loaded << std::endl; } 

your code correct has few mistakes:

you don't need making size_tag since serializing number of rows , columns explicitly. cereal uses size_tag resizable containers vectors or lists. though matrix can resize, makes more sense serialize rows , columns explicitly.

  1. your load function should accept parameter non-const reference
  2. you shouldn't use operator= std::ofstream objects
  3. it's better practice let scoping , raii handle closing/tearing down of std::ofstream cereal archives (the binary archive flush contents immediately, in general cereal archives guaranteed flush contents on destruction)

here's version compiles , produces correct output under g++ , clang++:

#include <cereal/cereal.hpp> #include <cereal/archives/binary.hpp> #include <eigen/dense> #include <fstream>  namespace cereal {   template <class archive, class _scalar, int _rows, int _cols, int _options, int _maxrows, int _maxcols> inline     typename std::enable_if<traits::is_output_serializable<binarydata<_scalar>, 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 <class archive, class _scalar, int _rows, int _cols, int _options, int _maxrows, int _maxcols> inline     typename std::enable_if<traits::is_input_serializable<binarydata<_scalar>, 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<std::size_t>(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; } 

Comments

Popular posts from this blog

apache - Remove .php and add trailing slash in url using htaccess not loading css -

javascript - jQuery show full size image on click -