Put the class serialization in the DLL

I am looking for a (working) example for external serialization of a cluster structure in a DLL. Currently, I cannot find examples for this. In the Boost documentation, there are only a few macros, forums, and newsgroups that simply discuss specific problems with their solutions.

So, I am asking an example for (from outside) serializing a class structure as follows. Along with the code class, I added some code for serialization (which does not work, see below for an error message).

class Foo { public: Foo() { number_ = 0; } virtual ~Foo() {} int getNumber() { return number_; } void setNumber( int var ) { number_ = var; } private: int number_; }; class Bar : public Foo { public: Bar() { doubleNumber_ = 0.0; } virtual ~Bar() {} double getDouble() { return doubleNumber_; } void setDouble( double var ) { doubleNumber_ = var; } private: double doubleNumber_; }; 

All I have so far is the code:

serializeFoo.h

 #ifndef _SERIALIZE_FOO_H_ #define _SERIALIZE_FOO_H_ #include "Foo.h" #include <boost/serialization/split_free.hpp> #include <boost/serialization/version.hpp> namespace boost { namespace serialization { template <typename Archive> void save(Archive& ar, const Foo& object, const unsigned int version) { ar << object.getNumber(); } template <typename Archive> void load(Archive& ar, Foo& object, const unsigned int version) { int number; ar >> number; object.setNumber(number); } }} //namespace brackets BOOST_SERIALIZATION_SPLIT_FREE( Foo ) #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/export.hpp> BOOST_CLASS_EXPORT_KEY( Foo ) #endif //_SERIALIZE_FOO_H_ 

serializeFoo.cpp

 #include "serializeFoo.h" BOOST_CLASS_EXPORT_IMPLEMENT( Foo ) 

serializeBar.h

 #ifndef _SERIALIZE_BAR_H_ #define _SERIALIZE_BAR_H_ #include "Bar.h" #include <boost/serialization/split_free.hpp> #include <boost/serialization/version.hpp> namespace boost { namespace serialization { template <typename Archive> void save(Archive& ar, const Bar& object, const unsigned int version) { ar << base_object<Foo>(object); ar << object.getDouble(); } template <typename Archive> void load(Archive& ar, Bar& object, const unsigned int version) { double doubleNumber; ar >> doubleNumber; object.setDouble(doubleNumber); } }} //namespace brackets BOOST_SERIALIZATION_SPLIT_FREE( Bar ) #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/export.hpp> BOOST_CLASS_EXPORT_KEY( Bar ) #endif //_SERIALIZE_BAR_H_ 

serializeBar.cpp

 #include "serializeBar.h" BOOST_CLASS_EXPORT_IMPLEMENT( Bar ) 

The serialization code goes into the DLL and should be used in another project using the Foo and Bar classes. Everything compiles fine, but at runtime I get a message
unregistered class - derived class not registered or exported

So did I use the wrong macros? Am I missing a macro? Is the above code correct or is there some kind of structural error? Perhaps this can be useful for many other people, I don’t think that including serialization of a class in a DLL is very exotic ...

+6
source share
4 answers

I ran into a similar problem recently, 3 years after this question was asked. I finally found a workaround to solve it. In the above example.

  • Bar is a subclass of Foo , so it must be registered / exported;
  • serializeFoo.cpp creates an instance of the GUID template class to register / export Foo ;
  • serializeBar.cpp creates an instance of the GUID template class for registering / exporting Bar ;
  • Rules for including all necessary archive types before exporting class keys are respected;
  • Both translation blocks are interconnected to create a DLL.

I assume that in your exe, when you try to serialize a Foo* pointer pointing to a Bar object, you get the error "unregistered blahblah class". This is because Boost.Serialization somehow does not generate a GUID for the Bar class before . The serialization function is called.

I don’t know why this is happening, but it seems that the GUID is generated in a lazy way - if not one of the characters from the translation unit serializeBar.cpp is used, not one of the creation / initialization code defined in this will translate the unit including registration / Bar class unloading.

To prove this, you can try using the (dummy) character in serializeBar.cpp (for example, by calling a dummy function implemented in serializeBar.cpp ) before calling any serialization function for Foo* . The problem should disappear.

Hope this helps.

+1
source

the test suite and demo distributed with the serialization library demonstrate this very possibility. So first make sure this works. Then compare your example with it.

Robert Rami

"Honestly, IMHO, in some cases, Boost Serialization crosses the line of what is reliably possible with a clean C ++ build model without external tools ..."

hmmmmmm - why does it cross the border as possible? But you are extremely faithful to the spirit. Great efforts have been spent on implementing everything that was considered necessary in order for such a package to be acceptable for promotion.

PP

+1
source

It's hard to say ... There are many chances that everything will go wrong. I recommend downloading test code to increase serialization (www.boost.org/doc/libs/1_48_0/libs/serialization/test/). Take a look at the test cases around Ah, A.cpp and dll_a.cpp (which basically test your script) and try to make it work outside the boost test system: use your build environment, try changing the compiler / linker settings to compatible with the boost package for your toolbox.

Honestly, IMHO, in some cases, Boost Serialization crosses the line of what is reliably possible with a clean C ++ build model without external tools ...

0
source

Use BOOST_CLASS_EXPORT to register all of your classes that you would like to serialize.

0
source

Source: https://habr.com/ru/post/907908/


All Articles