Boost logo

Boost Users :

Subject: Re: [Boost-users] [Serialization] Serialize base and derived classes.
From: BlueAngel (lists_at_[hidden])
Date: 2010-07-29 09:44:48


Il 29/07/2010 00:14, BlueAngel ha scritto:
> Il 28/07/2010 12:38, BlueAngel ha scritto:
>> Il 26/07/2010 18:58, BlueAngel ha scritto:
>>> Hi lists,
>>> I'm working with the Serialization library but I'm having some
>>> troubles with it.
>>> The tutorials in the website shown me much but still I need help.
>>>
>>> I'm using XML archives.
>>> I have this classes actually (these classes are all
>>> builders/prototypes, they serialize the datas and then they should
>>> make a new object with those datas):
>>> Serializer (an interface, every class which need serialization must
>>> be derived from this, however this is only a marker, it will be not
>>> serialized)
>>> RenderableSerializer : public Serializer - this isn't pure virtual
>>> however shouldn't be never serialized directly (since the object
>>> made by this class is a pure virtual one) - These will use the tag
>>> <renderable>
>>> SkyboxSerializer : public RenderableSerializer - these will use the
>>> tag <skybox>
>>> EntitySerializer : public Serializer - these will use the tag <entity>
>>> many other classes will be added in future and they'll all derive
>>> form RenderableSerializer.
>>>
>>>
>>> Now the problem is EntitySerializer have a pointer to a
>>> RenderableSerializer and when I serialize EntitySerializer the
>>> pointer to that class is considered to be a RenderableSerializer and
>>> not the derived class. I don't know at priori which class is the
>>> base class and this lead to problem.
>>> If I serialize a SkyboxSerializer I have the correct tag: a <skybox>
>>> which have inside a <renderable> and the datas are correct.
>>> If I try to serialize an Entity I had a lot of problem, mostly just
>>> make the library crash. As I've seen in the tutorial I should
>>> register all the derived classes before pass the pointer to the
>>> Archive. I did it registering the SkyboxSerializer classes but it
>>> lead to a wrong xml: a correct <entity> tag which have a correct
>>> <skybox> with all it's data but also a wrong <renderable> tag which
>>> have inside the same data of the tag <skybox> instead of the data of
>>> a RenderableSerializer class.
>>>
>>> Now the question is: is there a correct way to use the library this
>>> way? With a pointer to a base class of which the derived is not known?
>>> My code is too big and I made many attempt to use the library so I'm
>>> not posting it in this message. If you need it I will post it.
>>> Thank you for your replies.
>>>
>>>
>>> _______________________________________________
>>> Boost-users mailing list
>>> Boost-users_at_[hidden]
>>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>> It seems no one know the answer. I hope it's just I made a too vague
>> request. Here's the partial code (load function are implemented the
>> same way, simmetrically):
>> EntitySerializer.hpp:
>> void *save*(xml_oarchive& ar, const unsigned int version) const
>> {
>> ar << make_nvp("EntityName", _nome); // string
>> ar.register_type(static_cast<SkyBoxSerializer *>(NULL)); // Note:
>> this is just for debug, in the future I'll make a function in every
>> class derived from Serializer which register itself when needed.
>> ar << make_nvp(_renderable->getTagName().c_str(), _renderable);
>> }
>>
>> SkyboxSerializer.hpp:
>> void *save*(xml_oarchive& ar, const unsigned int version) const
>> {
>> ar << make_nvp("renderable",
>> boost::serialization::base_object< RenderableSerializer
>> >(*this));
>> //RenderableSerializer::save(ar, version); // If I use this line
>> instead of the previous it de/serializer correctly but I know this is
>> a dirty work-around and I want to avoid it.
>> ar << make_nvp("shader_file", _fx_file); // std::string
>> ar << make_nvp("mesh_file", _mesh_filename); // std::string
>> ar << make_nvp("cubemap_file", _tex_filename); // std::string
>> }
>> RenderableSerialier.hpp:
>> void *save*(xml_oarchive& ar, const unsigned int version) const
>> {
>> ar << make_nvp("scala", _scala); // struct vector
>> ar << make_nvp("rotazione", _rotazione); // struct vector
>> ar << make_nvp("posizione", _posizione); // struct vector
>> }
>> VectorSerializer.hpp:
>> struct vettore
>> {
>> float x, y, z;
>> };
>>
>> namespace boost
>> {
>> namespace serialization
>> {
>> template<class Archive> void *serialize*(Archive& ar, vettore& vec,
>> const unsigned int version)
>> {
>> ar & make_nvp("x", vec.x);
>> ar & make_nvp("y", vec.y);
>> ar & make_nvp("z", vec.z);
>> }
>> }
>> }
>>
>> Serializer.hpp:
>> virtual void *save*(xml_oarchive& ar, const unsigned int version)
>> const = 0;
>>
>> And this is the xml resultant:
>> <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
>> <!DOCTYPE boost_serialization>
>> <boost_serialization signature="serialization::archive" version="7">
>> <entity class_id="0" tracking_level="0" version="0">
>> <EntityName>skybohx</EntityName>
>> <skybox class_id="1" tracking_level="1" version="0" object_id="_0">
>> <renderable class_id="2" tracking_level="1" version="0" object_id="_1">
>> <renderable object_id_reference="_1"></renderable>
>> <shader_file>skybox.fx</shader_file>
>> <mesh_file>asd.x</mesh_file>
>> <cubemap_file>CubeMap.dds</cubemap_file>
>> </renderable>
>> <shader_file>skybox.fx</shader_file>
>> <mesh_file>asd.x</mesh_file>
>> <cubemap_file>CubeMap.dds</cubemap_file>
>> </skybox>
>> </entity>
>> </boost_serialization>
>>
>> As you can see the renderable tag inside the skybox tag is wrong. The
>> <renderable> should have:
>> <scala>
>> <x>3</x>
>> <y>3</y>
>> <z>3</z>
>> </scala>
>> <rotazione>
>> <x>2</x>
>> <y>2</y>
>> <z>2</z>
>> </rotazione>
>> <posizione>
>> <x>1</x>
>> <y>1</y>
>> <z>1</z>
>> </posizione>
>>
>> Why that tag serialize the derived class instead of itself?
>> Thank you again for your answers.
>>
>>
>> _______________________________________________
>> Boost-users mailing list
>> Boost-users_at_[hidden]
>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
> Hi,
> I don't want to insist but... I don't understand:
> The:
> ar << make_nvp("renderable",
> boost::serialization::base_object< RenderableSerializer >(*this));
> of the *save* function of SkyboxSerializer seems to call itself again
> instead of the save function of the RenderableSerializer.
> How can this happen?
>
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
I still hope someone can answer me.
I finally made everything work but with an issue: I had to remove the
*save/load* functions and use just the *serialize* function. At the
beginning I reverted all the functions above as template (like instead of
void *save*(xml_oarchive& ar, const unsigned int version) const
I reverted as:
template<class Archive> void *save*(Archive& ar, const unsigned int version)
and the same for the *load* function).
The result was that the library call only the *save/load* in
Serializer.hpp, there were no way to make it call the derived functions.
I tried to brutally cast the pointer to the base object (like: ar &
make_nvp(_tagName.c_str(), static_cast<SkyBoxSerializer&>(*this));
but I wont work, still the library call the functions in Serialier.hpp.

Now I reverted the functions to *serialize* instead of *save/load* and
now everything works fine, the derived function are called before the
base ones and
Why not with *save/load*?



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net