[serialization] save_construct_data problem
I have a structure I'm trying to serialize that contains an STL vector of pointers to an abstract base type. When I serialize it, the save_construct_data free function is NOT called - the inline default version is always used. On de-serializing, the load_construct_data IS called! but, of course, fails because the data for it isn't there (although it throws archive_exception (archive_exception::unregistered_class) when it fails). I'm using declarations only for all serialization code, with all definitions in .s.cpp files along with explicit instantiations. Not sure if that affects the problem here. Just in case, I've tried all combinations of save_construct_data with (const)? (Base|Derived) (*|&), and none of them are called. I've also tried putting my declarations before and after the serialization.hpp header with the default declaration/definition. I'm using gcc4 currently. Any notion what might be wrong here?
without seeing the code I'm not sure what to day.
Double check that namespace in which save_construct_data is
declared/defined.
Robert Ramey
"Hugh Hoover"
On Jul 9, 2006, at 15:02, Robert Ramey wrote:
without seeing the code I'm not sure what to day.
Double check that namespace in which save_construct_data is declared/defined.
the save/load construct_data code is all in boost::serialization.
The declarations look like:
in node.h:
class Node {
// normal stuff
virtual ~Node();
virtual void some_function() = 0;
private:
template <class Archive> void serialize(Archive& ar, const
unsigned int version);
};
in simplenode.h:
class SimpleNode : public Node {
// normal stuff
private:
template <class Archive> void serialize(Archive& ar, const
unsigned int version);
};
in node.hh:
BOOST_CLASS_TRACKING(Node, boost::serialization::track_always)
BOOST_IS_ABSTRACT(Node)
in simplenode.hh:
BOOST_CLASS_TRACKING(CSimpleNode, boost::serialization::track_always)
namespace boost {
namespace serialization {
template <class Archive>
CORE_DATA_API void load_construct_data(Archive& ar,
SimpleNode * sn,
const unsigned
int version);
template <class Archive>
CORE_DATA_API void save_construct_data(Archive& ar,
const SimpleNode*
sn,
const unsigned
int version);
// I've also tried the save with all combinations of Node and
SimpleNode, * and &, and const/nonconst.
}
}
In another header (nodeset.h) I have:
#include "node.h"
class NodeSet {
typedef std::vector
I have a structure I'm trying to serialize that contains an STL vector of pointers to an abstract base type. When I serialize it, the save_construct_data free function is NOT called - the inline default version is always used. On de-serializing, the load_construct_data IS called! but, of course, fails because the data for it isn't there (although it throws archive_exception(archive_exception::unregistered_class) when it fails).
In your test case you serialize SimpleNode instance
rather than a pointer. So I would ne expect
save_construct_data to be called in this case.
A couple of things don't look right to me.
a0 Node has a serialize function. But the program
also includes
boost::serialization::void_cast_register
NULL);
which I believe should be necessary only if the SimpleNode serialize function doesn't invoke base_object ... b) Of course I'm wondering what CORE_DATA_API might expand to - and if this might prevent the compiler from finding the specializaton. Robert Ramey Hubert Hoover wrote:
On Jul 9, 2006, at 15:02, Robert Ramey wrote:
without seeing the code I'm not sure what to day.
Double check that namespace in which save_construct_data is declared/defined.
the save/load construct_data code is all in boost::serialization.
The declarations look like:
in node.h: class Node { // normal stuff virtual ~Node();
virtual void some_function() = 0;
private: template <class Archive> void serialize(Archive& ar, const unsigned int version); };
in simplenode.h: class SimpleNode : public Node { // normal stuff private: template <class Archive> void serialize(Archive& ar, const unsigned int version); };
in node.hh: BOOST_CLASS_TRACKING(Node, boost::serialization::track_always) BOOST_IS_ABSTRACT(Node)
in simplenode.hh: BOOST_CLASS_TRACKING(CSimpleNode, boost::serialization::track_always)
namespace boost { namespace serialization { template <class Archive> CORE_DATA_API void load_construct_data(Archive& ar, SimpleNode * sn, const unsigned int version); template <class Archive> CORE_DATA_API void save_construct_data(Archive& ar, const SimpleNode* sn, const unsigned int version);
// I've also tried the save with all combinations of Node and SimpleNode, * and &, and const/nonconst. } }
In another header (nodeset.h) I have: #include "node.h"
class NodeSet { typedef std::vector
NodeVector; NodeVector m_nodes; // other stuff to make this useful
private: template <class Archive> void serialize(Archive& ar, const unsigned int version); }
template <class Archive> void register_my_types(Archive& ar);
The definitions and template instantiations (for serialization) are in *.s.cpp. I'm not sure they're pertinent here, the compiler doesn't see them when it's dealing with the code that calls what's in the headers.
in nodeset.s.cpp I have:
#include
#include #include
#include "node.hh" #include "simplenode.hh"
template <class Archive> void NodeSet::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_NVP(m_nodes); }
template <class Archive> void register_my_types(Archive& ar) { ar.register_type(static_cast
(NULL)); ar.register_type(static_cast (NULL)); boost::serialization::void_cast_register
(NULL, NULL); } In the test (calling) code, I have:
#include "node.hh" #include "simplenode.hh"
std::string calling_function(NodeSet& ns) { std::ostringstream oss; boost::archive::xml_oarchive oar(oss); register_my_types(oar); oar << ns; std::string res = oss.str(); return str; }
There's other code for readback, but it (so far) appears to be ok. There's obviously a LOT of actual detail missing, but I think I've included the essential bits. My actual test case is slightly more complex, as it includes several other classes - however, I have already gotten THOSE classes to properly serialize. I only ran into the problem when I added the Node and SimpleNode classes (NodeSet is actually represented by a different class, but it holds an m_nodes member exactly as shown here. I'd include more, but what with my other cruft and classes, my current test case is actually over 2000 lines... But again, I only ran into the problem with the addition of the above Node and SimpleNode classes.
I have a structure I'm trying to serialize that contains an STL vector of pointers to an abstract base type. When I serialize it, the save_construct_data free function is NOT called - the inline default version is always used. On de-serializing, the load_construct_data IS called! but, of course, fails because the data for it isn't there (although it throws archive_exception(archive_exception::unregistered_class) when it fails).
On Jul 9, 2006, at 21:24, Robert Ramey wrote:
In your test case you serialize SimpleNode instance rather than a pointer. So I would ne expect save_construct_data to be called in this case.
A couple of things don't look right to me.
a0 Node has a serialize function. But the program also includes
boost::serialization::void_cast_register
(NULL, NULL);
I've been finding it necessary on other classes, but I'll try removing it.
which I believe should be necessary only if the SimpleNode serialize function doesn't invoke base_object ...
b) Of course I'm wondering what CORE_DATA_API might expand to - and if this might prevent the compiler from finding the specializaton.
On gcc, it expands to nothing, on VC8, it expands to __declspec (dllexport) or __declspec(dllimport) as appropriate. I'm now trying to figure out what I did for my last change, because I'm now getting a linker undefined error for: boost::archive::text_iarchive_implboost::archive::text_iarchive::load_ override(boost::archive::class_name_type&, int) I thought it was just shifting where the boost/serialization headers get included, but switching back didn't restore the symbol... when I get that figured out, I'll get back to the problem of interest...
well, never mind ... The missing symbol was because I switched from 1_33 to 1_33_1 headers (which I thought I'd been using anyway), but forgot to switch the libs... el stupido... When I fixed THAT up, well, IT WORKS... (well, ok, not completely yet, but the written archive includes the save_construct_data at the proper place. On Jul 10, 2006, at 10:16, Hubert Hoover wrote:
On Jul 9, 2006, at 21:24, Robert Ramey wrote:
In your test case you serialize SimpleNode instance
participants (3)
-
Hubert Hoover
-
Hugh Hoover
-
Robert Ramey