|
Boost : |
From: Pascal Kesseli (pascal_kesseli_at_[hidden])
Date: 2007-12-27 18:30:54
Hi folks
Currently Im having quite some trouble with the boost serialization library. Take the following classes as given:
ProtocolFactory.h:
#ifndef PROTOCOLFACTORY_H_
#define PROTOCOLFACTORY_H_
#include <boost/serialization/access.hpp>
#include <boost/serialization/is_abstract.hpp>
#include <boost/shared_ptr.hpp>
class Meter;
typedef boost::shared_ptr<Meter> MeterPtr;
class MeteringProtocol;
typedef boost::shared_ptr<MeteringProtocol> MeteringProtocolPtr;
class ProtocolFactory {
public:
ProtocolFactory();
virtual ~ProtocolFactory();
virtual MeteringProtocolPtr getNewProtocolInstance(Meter *const) const = 0;
virtual MeteringProtocolPtr
getNewProtocolInstance(const MeterPtr &) const = 0;
private:
friend class boost::serialization::access;
template<class archive> void serialize(archive &, const unsigned int) {
}
};
BOOST_IS_ABSTRACT(ProtocolFactory);
typedef boost::shared_ptr<ProtocolFactory> ProtocolFactoryPtr;
#endif /*PROTOCOLFACTORY_H_*/
ProtocolFactory.cpp
#include "ProtocolFactory.h"
ProtocolFactory::ProtocolFactory() {
}
ProtocolFactory::~ProtocolFactory() {
}
Iec1107OverSerialFactory.h
#ifndef IEC1107OVERSERIALFACTORY_H_
#define IEC1107OVERSERIALFACTORY_H_
#include "ProtocolFactory.h"
class Iec1107OverSerialFactory : public ProtocolFactory {
public:
Iec1107OverSerialFactory();
virtual ~Iec1107OverSerialFactory();
virtual MeteringProtocolPtr getNewProtocolInstance(Meter *const) const;
virtual MeteringProtocolPtr getNewProtocolInstance(const MeterPtr &) const;
private:
friend class boost::serialization::access;
template<class archive> void serialize(archive &, const unsigned int);
};
#include "Iec1107OverSerialFactory.inc"
typedef boost::shared_ptr<Iec1107OverSerialFactory> Iec1107OverSerialFactoryPtr;
#endif /*IEC1107OVERSERIALFACTORY_H_*/
Iec1107OverSerialFactory.inc:
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/nvp.hpp>
BOOST_CLASS_EXPORT(Iec1107OverSerialFactory) // Boost must include Serialization info for this class even if its not directly referencd (e.g. by its base class)
template<class Archive> void Iec1107OverSerialFactory::serialize(Archive &ar, const unsigned int version) {
using boost::serialization::make_nvp;
ar & make_nvp("ProtocolFactory", boost::serialization::base_object<ProtocolFactory>(*this));
}
Iec1107OverSerialFactory.cpp:
#include "Iec1107OverSerialFactory.h"
#include "Iec1107OverSerial.h"
#include "../Meter.h"
#include "MeteringProtocol.h"
using namespace boost;
Iec1107OverSerialFactory::Iec1107OverSerialFactory() {
}
Iec1107OverSerialFactory::~Iec1107OverSerialFactory() {
}
MeteringProtocolPtr Iec1107OverSerialFactory::getNewProtocolInstance(
Meter *const target) const {
return MeteringProtocolPtr(new Iec1107OverSerial(target));
}
MeteringProtocolPtr Iec1107OverSerialFactory::getNewProtocolInstance(
const MeterPtr &target) const {
return MeteringProtocolPtr(new Iec1107OverSerial(target));
}
MeteringProtocolCompoisteFactory.h
#ifndef METERINGPROTOCOLCOMPOSITEFACTORY_H_
#define METERINGPROTOCOLCOMPOSITEFACTORY_H_
#include "ProtocolFactory.h"
#include <vector>
class MeteringProtocolCompositeFactory : public ProtocolFactory {
public:
MeteringProtocolCompositeFactory(const std::vector<ProtocolFactoryPtr> &);
virtual ~MeteringProtocolCompositeFactory();
virtual MeteringProtocolPtr getNewProtocolInstance(Meter *const) const;
virtual MeteringProtocolPtr getNewProtocolInstance(const MeterPtr &) const;
const std::vector<ProtocolFactoryPtr> &getFactories() const;
private:
std::vector<ProtocolFactoryPtr> factories;
friend class boost::serialization::access;
template<class archive> void serialize(archive &, const unsigned int);
};
#include "MeteringProtocolCompositeFactory.inc"
typedef boost::shared_ptr<MeteringProtocolCompositeFactory>
MeteringProtocolCompositeFactoryPtr;
#endif /*METERINGPROTOCOLCOMPOSITEFACTORY_H_*/
MeteringProtocolCompoisteFactory.inc
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/nvp.hpp>
BOOST_CLASS_EXPORT(MeteringProtocolCompositeFactory) // Boost must include Serialization info for this class even if its not directly referencd (e.g. by its base class)
namespace boost {
namespace serialization {
template<class Archive> inline void save_construct_data(Archive &ar, const MeteringProtocolCompositeFactory *pf, const unsigned int version) {
using boost::serialization::make_nvp;
ar & make_nvp("IncludedProtocols", pf->getFactories());
}
template<class Archive> inline void load_construct_data(Archive &ar, MeteringProtocolCompositeFactory *pf, const unsigned int version) {
using boost::serialization::make_nvp;
std::vector<ProtocolFactoryPtr> factories;
ar & make_nvp("IncludedProtocols", factories);
::new(pf)MeteringProtocolCompositeFactory(factories);
}
}
}
template<class Archive> void MeteringProtocolCompositeFactory::serialize(Archive &ar, const unsigned int version) {
using boost::serialization::make_nvp;
ar & make_nvp("ProtocolFactory", boost::serialization::base_object<ProtocolFactory>(*this));
}
MeteringProtocolCompositeFactory.cpp:
#include "MeteringProtocolCompositeFactory.h"
#include "MeteringProtocolComposite.h"
#include <iterator>
using namespace std;
MeteringProtocolCompositeFactory::MeteringProtocolCompositeFactory(
const vector<ProtocolFactoryPtr> &factories) :
factories(factories) {
}
MeteringProtocolCompositeFactory::~MeteringProtocolCompositeFactory() {
}
MeteringProtocolPtr MeteringProtocolCompositeFactory::getNewProtocolInstance(
Meter *const target) const {
vector<MeteringProtocolPtr> protocols;
for (vector<ProtocolFactoryPtr>::const_iterator it = factories.begin(); it
!= factories.end(); ++it) {
protocols.push_back((*it)->getNewProtocolInstance(target));
}
return MeteringProtocolPtr(new MeteringProtocolComposite(protocols));
}
MeteringProtocolPtr MeteringProtocolCompositeFactory::getNewProtocolInstance(
const MeterPtr &target) const {
vector<MeteringProtocolPtr> protocols;
for (vector<ProtocolFactoryPtr>::const_iterator it = factories.begin(); it
!= factories.end(); ++it) {
protocols.push_back((*it)->getNewProtocolInstance(target));
}
return MeteringProtocolPtr(new MeteringProtocolComposite(protocols));
}
const std::vector<ProtocolFactoryPtr> &MeteringProtocolCompositeFactory::getFactories() const {
return factories;
}
MeterType.h:
#ifndef METERTYPE_H_
#define METERTYPE_H_
#include <boost/serialization/access.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <vector>
class ProtocolFactory;
typedef boost::shared_ptr<ProtocolFactory> ProtocolFactoryPtr;
class MeterType {
public:
MeterType(const std::string &, const std::vector<std::string> &,
const ProtocolFactoryPtr &);
virtual ~MeterType();
const std::string &getTypeName() const;
const std::vector<std::string> &getRequestedDataItems() const;
const ProtocolFactoryPtr &getSupportedProtocols() const;
private:
MeterType();
std::string typeName;
std::vector<std::string> requestedDataItems; // include Data IDs like 1.8.1, standardized for all metering protocls (I hope :)
// TODO: Create ProtocolFactoryComposite, including a serialization
// TODO: Serialize supportedProtcols and add to constructor
ProtocolFactoryPtr supportedProtocols;
friend class boost::serialization::access;
template<class archive> void serialize(archive &, const unsigned int);
};
#include "MeterType.inc"
typedef boost::shared_ptr<MeterType> MeterTypePtr;
#endif /*METERTYPE_H_*/
MeterType.inc:
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <iostream>
namespace boost {
namespace serialization {
template<class Archive> inline void save_construct_data(Archive &ar, const MeterType *t, const unsigned int version) {
using boost::serialization::make_nvp;
ar & make_nvp("TypeName", t->getTypeName());
ar & make_nvp("RequestedDataItems", t->getRequestedDataItems());
ar & make_nvp("SupportedProtocols", t->getSupportedProtocols());
}
template<class Archive> inline void load_construct_data(Archive &ar, MeterType *t, const unsigned int version) {
using boost::serialization::make_nvp;
std::string typeName;
std::vector<std::string> requestedDataItems;
ProtocolFactoryPtr supportedProtocols;
ar & make_nvp("TypeName", typeName);
ar & make_nvp("RequestedDataItems", requestedDataItems);
ar & make_nvp("SupportedProtocols", supportedProtocols);
::new(t)MeterType(typeName, requestedDataItems, supportedProtocols);
}
}
}
template<class Archive> void MeterType::serialize(Archive &ar, const unsigned int version) {
}
MeterType.cpp:
#include "MeterType.h"
using namespace std;
MeterType::MeterType(void) {
}
MeterType::MeterType(const string &typeName,
const vector<string> &requestedDataItems,
const ProtocolFactoryPtr &supportedProtocols) :
typeName(typeName), requestedDataItems(requestedDataItems),
supportedProtocols(supportedProtocols) {
}
MeterType::~MeterType() {
}
const string &MeterType::getTypeName() const {
return typeName;
}
const vector<string> &MeterType::getRequestedDataItems() const {
return requestedDataItems;
}
const ProtocolFactoryPtr &MeterType::getSupportedProtocols() const {
return supportedProtocols;
}
Phew. Quite a list, I know :) . Anyway, to serialize these classes, I wrote the following code:
{
ofstream ofs("testIt.xml");
archive::xml_oarchive oxml(ofs);
oxml << serialization::make_nvp("supportedProtocols", iec1107);
}
ProtocolFactoryPtr newProtocolFactory;
ifstream ifs("testIt.xml");
archive::xml_iarchive ixml(ifs);
ixml >> serialization::make_nvp("supportedProtocols", newProtocolFactory);
which, however, throws an assert-failure in basic_iarchive.cpp at line 390. Uncommenting that line and recompiling allows me to fully and correctly execute the above code. However, when trying this:
{
ofstream ofs("testIt.xml");
archive::xml_oarchive oxml(ofs);
oxml << serialization::make_nvp("ZMD120", zmd120);
}
MeterTypePtr newType;
ifstream ifs("testIt.xml");
archive::xml_iarchive ixml(ifs);
ixml >> serialization::make_nvp("ZMD120", zmd120);
The Program crashes with a segmentation fault. Using Insight, i found the very line this happens: Its in MeterType.inc at line 22:
ar & make_nvp(SupportedProtocols, supportedProtocols);
Since I imagine this to be more or less exactly the same code as I executed before, without the MeterType class, Im not quite sure why this should fail. Anyway, can anyone lend me a hand here? Firstly, why would the assertion error occur? And why does serializing ProtocolFactoryPtr one time work and another time fail?
Thank you for any help and best regards
Kessi
_________________________________________________________________
Drück deine Gefühle aus! Hol dir 30 GRATIS Emoticons für den Windows Live Messenger!
http://get.live.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk