Polymorphic serialization with boost
Posted: Tue Nov 26, 2019 2:00 pm
Dear all!
I have a problem using RCF 2.2.0.0 with boost serialization for polymorphic types.
I want to change an instance of B passed via a reference of base class A. Using SF it works as expected:
However, with boost, the derived class' serialization is not called and the value is unchanged.
I'm aware that both RCF 2.x and boost serialization are deprecated. However, for the project I'm working on it's a requirement to use at least the boost serialization.
Could you please give me a hint on how to make it work?
You can find my minimal example below.
Thanks in advance,
Sebastian
I have a problem using RCF 2.2.0.0 with boost serialization for polymorphic types.
I want to change an instance of B passed via a reference of base class A. Using SF it works as expected:
Code: Select all
Calling the I_SetService Set() method.
B::SF_serialize
A::SF_serialize
B::SF_serialize
A::SF_serialize
B::set() 42
B::SF_serialize
A::SF_serialize
B::SF_serialize
A::SF_serialize
42 expected 42
Code: Select all
Calling the I_SetService Set() method.
A::boost_serialize saving
B::boost_serialize saving
A::boost_serialize loading
B::boost_serialize loading
B::set() 42
A::boost_serialize saving
A::boost_serialize loading
1 expected 42
Could you please give me a hint on how to make it work?
You can find my minimal example below.
Thanks in advance,
Sebastian
Code: Select all
#include <fstream>
#include <iostream>
#include "RCF/RCF.hpp"
#ifndef RCF_USE_BOOST_SERIALIZATION
#include "SF/Registry.hpp"
#include "SF/SerializeParent.hpp"
#endif
#include <boost/serialization/export.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/serialization.hpp>
class A
{
public:
virtual void set(int /*i*/)
{
throw std::runtime_error("A::set() is not expected to be called");
};
#ifndef RCF_USE_BOOST_SERIALIZATION
void serialize(SF::Archive& /*ar*/) { std::cout << "A::SF_serialize\n"; }
#endif
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive& ar, unsigned int const /* version */)
{
std::cout << "A::boost_serialize "
<< (typename Archive::is_loading() ? "loading" : "saving") << '\n';
}
};
BOOST_CLASS_EXPORT(A)
class B : public A
{
public:
B() : s(1){};
void set(int i) override
{
std::cout << "B::set() " << i << "\n";
s = i;
}
int s;
#ifndef RCF_USE_BOOST_SERIALIZATION
void serialize(SF::Archive& ar)
{
std::cout << "B::SF_serialize\n";
SF::serializeParent<A>(ar, *this);
ar& s;
}
#endif
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive& ar, unsigned int const /* version */)
{
using namespace boost::serialization;
ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
ar& make_nvp("s", s);
std::cout << "B::boost_serialize "
<< (typename Archive::is_loading() ? "loading" : "saving") << '\n';
}
};
BOOST_CLASS_EXPORT(B)
RCF_BEGIN(I_SetService, "I_SetService")
RCF_METHOD_V2(void, Set, A&, int)
RCF_END(I_SetService)
class SetService
{
public:
void Set(A& a, int i) { a.set(i); }
};
int main()
{
try {
#ifndef RCF_USE_BOOST_SERIALIZATION
SF::registerType<B>("B");
SF::registerBaseAndDerived<A, B>();
#endif
RCF::RcfInitDeinit rcfInit;
RCF::RcfServer server(RCF::TcpEndpoint("127.0.0.1", 50001));
SetService printService;
server.bind<I_SetService>(printService);
server.start();
RcfClient<I_SetService> client(RCF::TcpEndpoint("127.0.0.1", 50001));
B b = B();
A& a = b;
int const value = 42;
std::cout << "Calling the I_SetService Set() method." << std::endl;
client.Set(a, value);
std::cout << b.s << " expected " << value << '\n';
} catch (const RCF::Exception& e) {
std::cout << "Error: " << e.what() << std::endl;
}
return 0;
}