490 likes | 725 Views
The Boost Serialization Library. Robert Ramey Santa Barbara, California ramey@rrsd.com March 6, 2008. What is “Serialization”. // create class instance const gps_position g(35, 59, 24.567f); // save data to archive { // create and open a standard stream std::ofstream ofs("filename");
E N D
The Boost Serialization Library Robert Ramey Santa Barbara, California ramey@rrsd.com March 6, 2008
// create class instance const gps_position g(35, 59, 24.567f); // save data to archive { // create and open a standard stream std::ofstream ofs("filename"); // use it to build and archive boost::archive::text_oarchive oa( ofs ); // write class instance to archive oa << g; // on leaving scope // destructors close output stream }
// ... some time later restore the class instance // to its original state gps_position newg; { // create and open standard stream // for file input std::ifstream ifs("filename"); // and attach it to an input archive boost::archive::text_iarchive ia( ifs ); // read class state from archive ia >> newg; // on leaving scope // destructors close input stream }
if oa is an output or saving archive, the following operations must be supported for all serializable types. oa << x oa & x Both of these operations save data item x to the archive oa Saving Archive Summary
if ia is an input or loading archive, the following operations must be supported for all serializable types. ia >> x ia & x Both of these operations load data item x from the archive ia Loading Archive Summary
binary_oarchive / binary_iarchive Smallest Fastest Non-portable text_oarchive / text_iarchive Larger Slower Portable xml_oarchive / xml_iarchive Largest Slowest Portable
a primitive type. a class type and one of the following has been declared a free function serialize a class member function serialize a pointer to a Serializable type. a reference to a Serializable type. a native C++ Array of a Serializable type. Serializable Types
class my_class { friend serialization::access int a; template<class Archive> void serialize( Archive & ar, const unsigned int version ){ ar & a; } }; Making a class type serializablewith a member function
class my_class { friend serialization::access; int a; }; Making a class type serializablewith a free function
template<class Archive> inline void serialize( Archive & ar, my_class & t, const unsigned int version ){ ar & t.a; } A Free Function serialize
class gps_position { private: int degrees; int minutes; float seconds; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & degrees; ar & minutes; ar & seconds; } public: gps_position(){}; gps_position(int d, int m, float s) : degrees(d), minutes(m), seconds(s) {} };
// create class instance const gps_position g(35, 59, 24.567f); // save data to archive { // create and open a standard stream std::ofstream ofs("filename"); // use it to build and archive boost::archive::text_oarchive oa( ofs ); // write class instance to archive oa << g; // on leaving scope // destructors close output stream }
Serializing base class information Class versioning Splitting serialization function into separate load/save functions Other topics for class serialization
#include <boost/serialization/base_object.hpp> // includes the following template<class Base, class Derived> Base & base_object(Derived &d); … { // invoke serialization of the base class ar & base_object<base_class_of_T>(*this); // save/load class member variables ar & member1; ar & member2; } Serializing base class information
#include <boost/serialization/version.hpp> class my_class { int member1; int member2; // add new member added here template<class Archive> void serialization( Archive & ar, const unsigned int version ); }; // specify class version BOOST_CLASS_VERSION(my_class, 2) Class versioning(continued)
#include <boost/serialization/version.hpp> template<class Archive> void serialization( Archive & ar, const unsigned int version ){ // save/load class member variables ar & member1; // if its a recent version of the class if(1 < version) // save/load recently added class members ar & member2; } Class versioning
template<class Archive> void my_class::serialize(Archive & ar, const unsigned int version ){ if(Archive::is_saving::value){ ar << ... ; // append data to archive ar << crc(this, sizeof(*this); // append a crc } else{ unsigned int crc_value; ar >> ...; // read data from archive ar >> crc_value; // read the crc if(crc_value != crc(this, sizeof(*this)) throw crc_exception(); } } Splitting serialization function(1)
template<class Archive> void my_class::save( Archive & ar, const unsigned int version ) const { ar << ... ; // append data to archive ar << crc(this, sizeof(*this)// append a crc for this class to archive } template<class Archive> void my_class::load( Archive & ar, const unsigned int version ){ unsigned int crc_value; ar >> ...; // read data from archive ar >> crc_value; if(crc_value != crc(this, sizeof(*this)) throw crc_exception(); } BOOST_SERIALIZATION_SPLIT_MEMBER() Splitting serialization function(2)
// create array of positions const gps_position g_array[] = { gps_position(35,59, 23.123), gps_position(36,58, 23.123), }; // save data to archive { // create and open a standard stream std::ofstream ofs("filename"); // use it to build and archive boost::archive::text_oarchive oa( ofs ); // write class instance to archive oa << g_array; // on leaving scope // destructors close output stream }
// create a pointer to a gps position const gps_position g = gps_position(35,59, 23.123; const gps_position * g_ptr = & g; // save it (and the data it points to) to the archive { // create and open a standard stream std::ofstream ofs("filename"); // use it to build and archive boost::archive::text_oarchive oa(ofs); // write class instance being pointed to // to the archive oa << g_ptr; // on leaving scope // destructors close output stream }
// load a saved pointer gps_position * g_ptr; // create new data and load pointer to it { // create and open a standard stream std::ifstream ifs("filename"); // use it to build and archive boost::archive::text_iarchive ia(ifs); // allocate space for a gps_position on the heap // and load data from the archive into it ia >> g_ptr; // on leaving scope // destructors close output stream }
A new object instance has to be allocated on the heap. Then the data can loaded into it from the archive. Addresses of data serialized on through pointers must be tracked so that if the same data is saved twice, only one instance of the data is created during load. This is referred to as “tracking”. It is (usually) handled automatically by the library. To serialize a pointer
The data from the most derived class is serialized. Since serialization code for these classes is never explicitly referred to in the program, special precautions must be take to ensure that the serialization code is included in executable module. Available methods are “registration” and “export” Polymorphic pointers
class derived_one : public base { ... virtual ~derived_one(); }; main(){ ... ar.template register_type<derived_one>(); base *b; ... ar & b; } Registration
#include <boost/serialization/export.hpp> class derived_one : public base { ... virtual ~derived_one(); }; BOOST_CLASS_EXPORT(derived_one) main(){ ... base *b; ... ar & b; } Export
class bus_stop { … gps_position latitude; … }; Produces the following output in an xml archive: <latitude class_id="9" tracking_level="0"> <degrees>34</degrees> <minutes>135</minutes> <seconds>52.560001</seconds> </latitude> Serialization Wrappers
binary_objects Serialize data an opaque binary block. array Serialize an array exploiting special array handling BOOST_STRONG_TYPEDEF Create a type alias. Used to temporarily assign a serialization trait (described below) Other wrappers are:
template<class T> struct nvp : public std::pair<const char *, T *>, public wrapper_traits<nvp<T> > { … template<class Archive> void serialization( Archive & ar, const unsigned int ){ ar & *(this->second); } template<class Archive> BOOST_SERIALIZATION_SPLIT_MEMBER() }; Serialization Wrappers
xml_oarchive & xml_operator::operator <<(const nvp<T> & t){ *this << t.first; // output name of item *this << *(t.second); // output value of item return & this; } Special xml_archive Override
class bus_stop { … gps_position latitude; template<class Archive> void serialize(Archive &ar, const unsigned int version){ ar & BOOST_SERIALIZATION_NVP(name) } }; Serialization Wrappers(2)
Attributes assigned to types which affect the serialization of that type. Serialization Traits
BOOST_CLASS_VERSION( class name, version number ) Version
not_serializable primitive_type object_serializable object_class_info BOOST_CLASS_IMPLEMENTATION( class name, implementation level ) Implementation Level
track_never track_selectively track_always BOOST_CLASS_TRACKING( class name, tracking level ) Object Tracking
BOOST_CLASS_EXPORT( class name ) BOOST_CLASS_EXPORT_GUID( class name, "class_external_identifier“ ) Export key
is_saving is_loading oa << x oa & x save_binary(u, count) register_type<T>() / register_type(u) library_version() Saving Archive Concept
is_saving is_loading oa << x oa & x save_binary(u, count) register_type<T>() / register_type(u) library_version() Saving Archive Concept
#include <boost/archive/detail/common_oarchive.hpp> class trivial_oarchive : public boost::archive::detail::common_oarchive< trivial_oarchive > { friend class boost::archive::save_access; template<class T> void save(T & t); public: void save_binary( const void *address, std::size_t count ); }; Saving Archive Implementation
Archive Implementation interface_iarchive <text_iarchive> basic_iarchive common_iarchive <text_iarchive> basic_text_iarchive <text_iarchive> basic_text_iprimitive <basic_istream> text_iarchive_impl <text_iarchive> text_iarchive
Code is regenerated and compiled for each combination of archive class and data type. Much inline code may be replicated. If serialization code is placed in a DLL, the main motivations for using a DLL is defeated. Archives are implemented as templates
#include <boost/archive/polymorphic_iarchive.hpp> #include <boost/archive/polymorphic_iarchive.hpp> #include "A.hpp" // explicitly instantiate code for polymorphic archive template void A::serialize<polymorphic_iarchive>( polymorphic_iarchive, const unsigned int ); template void A::serialize<polymorphic_oarchive>( polymorphic_oarchive, const unsigned int ); Code in DLL
#include <boost/archive/polymorphic_text_iarchive.hpp> #include "A.hpp" int main(int argc, char* argv[]) { A a; std::stringstream ss; // instantiate archive which inherits polymorphic // interface and the normal text archive implementation polymorphic_text_iarchive oa(ss); polymorphic_iarchive & ia_interface = ia; ia_interface << a; } Code in main line
Polymorphic Archives interface_iarchive <polymorphic_iarchive> polymorphic_iarchive_impl text_iarchive_impl <text_iarchive> polymorphic_iarchive polymorphic_iarchive_route <text_iarchive_impl< text_iarchive > > polymorphic_text_iarchive