Serialization with BOOST _CLASS_EXPORT_KEY() is not the same as registert_type<>()

Hi, I’m trying to serialize a derived object with polymorphism into a file and deserialize to a base class pointer. This works when I use the register_type function but not the BOOST_CLASS_EXPORT_KEY() and BOOST_CLASS_IMPLEMENT() macros. I need to use the macros since I am using shared libraries. Here is a sample of code to demonstrate the problem. When run it gets a unregistered class exception. I’m using RHEL 7.4 with Boost 1.53. cat testera.h #ifndef testera_h #define testera_h #include <boost/serialization/serialization.hpp> #include <boost/archive/polymorphic_oarchive.hpp> #include <boost/archive/polymorphic_iarchive.hpp> #include <boost/serialization/export.hpp> #include <boost/serialization/string.hpp> class A { private: friend class boost::serialization::access; template< class Arch > void serialize( Arch &ar, const unsigned int ver ); public: A(); virtual ~A() {} void setStr( const std::string &s ); std::string getStr(); protected: std::string myStr; }; BOOST_CLASS_EXPORT_KEY(A) #endif boost_ptr> cat testera.C #include "testera.h" BOOST_CLASS_EXPORT_IMPLEMENT(A) template void A::serialize<boost::archive::polymorphic_oarchive>( boost::archive::polymorphic_oarchive &ar, const unsigned int ver ); template void A::serialize<boost::archive::polymorphic_iarchive>( boost::archive::polymorphic_iarchive &ar, const unsigned int ver ); A::A() : myStr( "a" ) { } void A::setStr( const std::string &s ) { myStr = s; } std::string A::getStr() { return myStr; } template<class Arch> void A::serialize( Arch &ar, const unsigned int ver ) { ar & myStr; } boost_ptr> cat testerb.h #ifndef testerb_h #define testerb_h #include "testera.h" class B : public A { private: friend class boost::serialization::access; template< class Arch > void serialize( Arch &ar, const unsigned int ver ); public: B(); virtual ~B() {} void set( const int i ); int get(); protected: int myI; }; BOOST_CLASS_EXPORT_KEY(B) #endif boost_ptr> cat testerb.C #include "testerb.h" BOOST_CLASS_EXPORT_IMPLEMENT(B) template void B::serialize<boost::archive::polymorphic_oarchive>( boost::archive::polymorphic_oarchive &ar, const unsigned int ver ); template void B::serialize<boost::archive::polymorphic_iarchive>( boost::archive::polymorphic_iarchive &ar, const unsigned int ver ); B::B(): myI( 1 ) { myStr = "b"; } void B::set( const int i ) { myI = i; } int B::get() { return myI; } template< class Arch > void B::serialize( Arch &ar, const unsigned int ver ) { // boost::serialization::void_cast_register< B, A >( static_cast< B *>( NULL ), static_cast< A * >( NULL ) ); ar & boost::serialization::base_object<A>( *this ); ar & myI; } int main( int argc, char *argv[] ) { int ret = 0; B obj; B obj2; obj.set( 2 ); A *ptr = NULL; B *bptr = NULL; bptr = &obj; ptr = &obj; if( argc > 1 ) { std::string fl = argv[ 1 ]; { std::ofstream ofl( fl.c_str() ); boost::archive::polymorphic_text_oarchive toar( ofl ); boost::archive::polymorphic_oarchive *oar = &toar; /* oar->register_type(static_cast<A *>(NULL)); oar->register_type(static_cast<B *>(NULL)); */ try { *oar & obj; // *oar & ptr; } catch( std::exception &e ) { std::cerr << "Error: archive from B to file " << fl << " - " << e.what() << std::endl; ret = 1; } } if( ! ret ) { ptr = NULL; bptr = NULL; { std::ifstream ifl( fl.c_str() ); boost::archive::polymorphic_text_iarchive tiar( ifl ); boost::archive::polymorphic_iarchive *iar = &tiar; /* iar->register_type(static_cast<A *>(NULL)); iar->register_type(static_cast<B *>(NULL)); */ try { *iar & ptr; // *iar & bptr; } catch( std::exception &e ) { std::cerr << "Error: archive from file " << fl << " to B * - " << e.what() << std::endl; ret = 1; } } if( ! ret ) { // std::cout << bptr->get() << std::endl; std::cout << static_cast<B*>( ptr )->get() << std::endl; } } } return ret; } testera and testerb are compiled into a shared library with this: boost_ptr> cat Makefile_lib CXXFLAGS = -c -ggdb3 -fPIC -funswitch-loops -fgcse-after-reload -std=c++11 LDFLAGS = -std=c++11 -lboost_serialization -lboost_thread -lboost_system -lboost_filesystem OBJLOC = obj OBJS = $(OBJLOC)/testera.o \ $(OBJLOC)/testerb.o LIBRARY_NAME = libtester.so libs:$(LIBRARY_NAME) $(LIBRARY_NAME): $(OBJS) ${CXX} -shared -o $@ $(OBJS) $(OBJLOC)/%.o: ./%.C $(CXX) $(CXXFLAGS) ./$*.C -o $(OBJLOC)/$*.o tester_mn is compiled into the executable with this: boost_ptr> cat Makefile_mn CXXFLAGS = -ggdb3 -funswitch-loops -fgcse-after-reload -std=c++11 LDFLAGS = -lboost_serialization -lboost_thread -lboost_system -lboost_filesystem -L. -ltester tester_mn: tester_mn.o ${CXX} $(CXXFLAGS) $(LDFLAGS) tester_mn.C -o $@ If I were to comment out the BOOST macros and uncomment the register_type() functions from tester_mn.C everything works. Is there a way to get the macros to work? -- Ray Kosby Software Engineer Columbus Technologies and Services, Inc www.columbususa.com<http://www.columbususa.com> Office - (301) 286-5095, fax - (301) 286-7475 NASA Goddard Space Flight Center, MS 452.1 Bldg 13 Rm 141 8800 Greenbelt Rd Greenbelt, MD 20771 USA
participants (1)
-
Kosby, Ray B. (GSFC-428.0)[COLUMBUS TECHNOLOGIES AND SERVICES INC]