Boost: serialization (download)

I use boost: serialization to save data structures to a file. Actual data is a pointer vector to classes and subclasses. However, the constructor of a class that is serialized takes another instance of the Agent class as a parameter, which is the object that controls communication with the modeling API (webots). I see that in boost :: serialization examples, serializable objects need an empty constructor class () {}; which will be used for reconstruction. However, this is not practical in my case. How can I use reconstruction, but include an object that interacts with the API? One of the serializable classes has this constructor:

State(Agent &A, ACTION_MODE const& m); 

and I saw from examples in boost documents that I needed something like this:

 State() {}; 

However, agent & A must be passed as a parameter. Should I find a way around this (using extern, singleton, global object), or is there a way to change this behavior on recovery? I'm sure something is missing here.

thanks

EDIT: Maybe I didn’t explain it enough. I get an error when trying to “download” by restoring serialized data.

 error: no matching function to call State::State() 

This is what made me look into boost :: serialize code and think that it was invoking a constructor or copy statement. How can I use a specific constructor to serialize data and take agent & a link as an argument?

EDIT # 2:

 template <class S, class P, class A> void Task<S,P,A>::save(const char* file) { std::ofstream ofs(file); assert(ofs.good()); boost::archive::text_oarchive oa(ofs); oa << states; ofs.close(); } template <class S, class P, class A> void Task<S,P,A>::load(const char* file) { std::ifstream ifs(file); boost::archive::text_iarchive ia(ifs); ia >> states; ifs.close(); } 

States are friend for increasing :: serialization :: access and serialization functions. Saving works fine, loading problem. states: boost::ptr_vector<S> states; where S is the type of polymorphic class of state.

State is a base class and has serialization

 template <class Archive> void State::serialize(Archive& ar, const unsigned int version) { ar & accel.Xaxis & accel.Yaxis & accel.Zaxis; ar & gyro.Xaxis & gyro.Yaxis & gyro.Zaxis; ar & gps.Yaxis; ar & positions; ar & reward & value & hash_value; } 

guState inherits from state.

 template <class Archive> void guState::serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object<State>(*this); ar & accel.Xaxis & accel.Yaxis & accel.Zaxis; ar & gyro.Xaxis & gyro.Yaxis & gyro.Zaxis; ar & gps.Yaxis; ar & positions; ar & reward & value & hash_value; } 

accel, gyro, gps - simple structures with three double variables. They are serialized above ^^. Positions are std::map<std::string,float> positions;

Looking at the serialized text file, everything looks OK. I can’t understand why it calls the constructor when trying to load a file.

EDIT # 3:

Base constructor:

 State(Agent &A, ACTION_MODE const& m); 

Derived Constuctor:

 guState::guState(Agent& A, ACTION_MODE const& m) : State(A, m) { ... } 

The reference to agents A contained in each state (or derivative state) refers to an object obtained from the modeling API. He controls a robot. I cannot serialize it, and it does not make sense to serialize it.

When i use:

 namespace boost { namespace serialization { template <class Archive> void save_construct_data(Archive & ar,const guState* d,const unsigned int file_version) { ar << guState::caller; ar << guState::mode; } template <class Archive> void load_construct_data(Archive & ar, guState* d,const unsigned int file_version) { Agent &a; ACTION_MODE &m; ar >> a; ar >> m; ::new(d) guState(a,m); } } } 

I get the following errors:

 invalid use of non-static data member State::caller invalid use of non-static data member State::mode 

referring to the links used from the constructor. A:

 error: 'a' declared as reference but not initialized error: 'm' declared as reference but not initialized 

As you can see, it makes no sense to try to save the link to the Agent, because this link (even if it can be saved or serialized) is likely to be different each time the application is launched.

And when loading construction data, except for me, perhaps using the wrong syntax, it makes no sense to build from a serialized link to the agent.

What I need is a way to tell load_construct_data how to get a link to the Agent (after initializing the agent object) and use this link to build the data.

Does that make sense? Do you think this is doable?

Edit # 4

 namespace boost { namespace serialization { template <class Archive> void save_construct_data(Archive & ar,const guState* d,const unsigned int file_version) { ar << guState::caller; } template <class Archive> void load_construct_data(Archive & ar, guState* d,const unsigned int file_version) { Agent * a; ACTION_MODE mode = RAND_SING; ar >> a; ::new(d) guState(*a,mode); } } } 

This will not allow to serialize guState :: caller

I also serialized the Agent class and overloaded the agent load_construct_data and save_construct_data to request a new instance of the agent to control the API from the modeling application.

+4
source share
1 answer

EDIT:

There is part of a tutorial that I think we both skipped: section constructors that are not standard here . For it to work, you need to execute the save_construct_data and load_construct_data . There is little technicality in terms of where these friendships are explored here .

In addition, you said that you had this problem when trying to download only, but you could save. It makes me think you might have missed

 BOOST_CLASS_EXPORT_GUID(state, "state") 

This omission can lead to segmentation errors after receiving load compilation (see the export section in the manual)

To be sure that I was not mistaken, I made a compilation example, which I will add if it is useful.

 #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/export.hpp> #include <iostream> #include <fstream> //base class struct base { base(double d) : m_d(d) {} virtual double run() = 0; private: friend class boost::serialization::access; double m_d; template <class Archive> void serialize(Archive& ar, const unsigned int version) { ar & m_d; } }; //forward declare the save construct data before friending it // (something about friend being in a different namespace) class derived; namespace boost { namespace serialization { template<class Archive> inline void save_construct_data(Archive & ar, const derived * t, const unsigned int file_version); }} //derived class with non-default constructor struct derived : public base { derived(double a , double b) : base(a+b), m_a(a),m_b(b),m_c(a*b) {} //some checks double get_a() const {return m_a;} double get_b() const {return m_b;} double get_c() const {return m_c;} double run(){return 1.0;} private: friend class boost::serialization::access; template<class Archive> friend void boost::serialization::save_construct_data(Archive & ar, const derived * t, const unsigned int file_version); template <class Archive> void serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object<base>(*this); //only need to return c, a and b already done for constructor ar & m_c; } double m_a, m_b, m_c; }; //Save and load the data required for the constructor. namespace boost { namespace serialization { template <class Archive> inline void save_construct_data( Archive & ar,const derived* d,const unsigned int file_version ) { // save data required to construct instance ar << d->m_a; ar << d->m_b; } template <class Archive> inline void load_construct_data( Archive & ar, derived* d,const unsigned int file_version ) { double a,b; ar >> a; ar >> b; // invoke inplace constructor to initialize instance of my_class ::new(d) derived(a,b); } } } //register the derived class with boost. BOOST_CLASS_EXPORT_GUID(derived, "derived") int main (int ac, char **av) { std::ofstream ofs("filename"); base* p = new derived(2,3); // save data to archive { boost::archive::text_oarchive oa(ofs); oa << p; } // ... some time later restore the class instance to its orginal state base* p2; { std::ifstream ifs("filename"); boost::archive::text_iarchive ia(ifs); ia >> p2; } derived* d = static_cast<derived*>(p2); std::cout<<"p2 vals are: "<<d->get_a()<<" "<<d->get_b()<<" "<<d->get_c()<<std::endl; } 

OLD RESPONSE:

I'm not sure that I fully understood your problem (a more complete example will help me) A constructor usually does not enter it when serializing an object: do you serialize raw data?

You mean that you don’t want to serialize all the raw data of the object, but just want to restore it again when you deserialize the object (using the constructor)? If so, you can do this by arranging the data needed to recover and separate the save and load operations.

 struct my_class { my_class(Agent& A, ACTION_MODE const & m) : m_state(A,M) {} private: State m_state; friend class boost::serialization::access; void save(Archive & ar, const unsigned int version) const { // note, version is always the latest when saving Agent tmp_A = m_state.get_A(); ACTION_MODE tmp_m = m_state.get_m(); ar & tmp_A; ar & tmp_m; } template<class Archive> void load(Archive & ar, const unsigned int version) { Agent tmp_A; ACTION_MODE tmp_m ar & tmp_A; ar & tmp_m; m_state = State(tmp_A,tmp_m); } BOOST_SERIALIZATION_SPLIT_MEMBER() } 

Does this help, or did I miss it?

+4
source

All Articles