|
Boost Users : |
Subject: Re: [Boost-users] [Boost Serialization] Problem serializing derived class declared in DLL
From: Guy Prémont (guy.premont_at_[hidden])
Date: 2011-04-06 10:50:09
Hi,
I use serialization of derived class in DLLs, actually several DLLs, so I guess it works.
In BASE.DLL I have the class Base, and in DERIVED.DLL i have the class Derived. The following shows the necessary contents of Base.h/cpp and Derived.h/cpp.
There are some issues that are mostly due to the fact that serialization depends on singleton to know how to serialize a given type. Multiple singletons in DLLs are the main problem, but setting "track always" do help.
Hope it helps.
Guy
===================
Base.h
class DLLSPEC Base
{
[...]
// only declaration
template<class Archive>
void serialize(Archive & ar, const unsigned int version);
}
BOOST_CLASS_TRACKING(Base, boost::serialization::track_always)
BOOST_CLASS_EXPORT_KEY2(Base, "Base")
BOOST_CLASS_VERSION(Base, 2)
=====================
Base.cpp
template<class Archive>
void Base::serialize(Archive & ar, const unsigned int version)
{
[...] // the implementation
}
// force the template instantiation for each archive types you use (typically xml_iarchive and xml_oarchive
template DLLSPEC void Base::serialize(A& ar, const unsigned int version);
BOOST_CLASS_EXPORT_IMPLEMENT(Base)
===================
Derived.h
class DLLSPEC Derived
{
[...]
// only declaration
template<class Archive>
void serialize(Archive & ar, const unsigned int version);
}
BOOST_CLASS_TRACKING(Derived, boost::serialization::track_always) // maybe needed
BOOST_CLASS_EXPORT_KEY2(Derived, "Derived")
BOOST_CLASS_VERSION(Derived, 28)
=====================
Derived.cpp
template<class Archive>
void Derived::serialize(Archive & ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
[...] // the implementation
}
// force the template instantiation for each archive types you use (typically xml_iarchive and xml_oarchive
template DLLSPEC void Derived::serialize(A& ar, const unsigned int version);
BOOST_CLASS_EXPORT_IMPLEMENT(Derived)
=========================
-- Guy Prémont, D.Sc. Architecte logiciel senior / Senior software architect CM Labs Simulations Inc. http://www.cm-labs.com/ Tel. 514-287-1166 ext. 237 > -----Original Message----- > From: boost-users-bounces_at_[hidden] [mailto:boost-users- > bounces_at_[hidden]] On Behalf Of Kolb, Jeremy > Sent: Wednesday, April 06, 2011 9:20 AM > To: boost-users_at_[hidden] > Subject: Re: [Boost-users] [Boost Serialization] Problem serializing > derived class declared in DLL > > I was never able to get this working properly either. I really like > the serialization library but it's impossible to use if you have > multiple derived classes across DLLs. > > Jeremy > > > -----Original Message----- > > From: boost-users-bounces_at_[hidden] [mailto:boost-users- > > bounces_at_[hidden]] On Behalf Of François Mauger > > Sent: Tuesday, April 05, 2011 6:13 PM > > To: boost-users_at_[hidden] > > Subject: Re: [Boost-users] [Boost Serialization] Problem serializing > > derived class declared in DLL > > > > Hi, > > > > >>>kmdarkmaster a écrit : > > > Dear Boost community, > > > > > > My problem is simple : I need to serialize a derived class (named > > Plugin) of > > > a c++ class (named Base) in my main program. > > > > > > The derived class Plugin is declared in a DLL which is load > > explicitely > > > during execution. > > > > > > I tried to use the macro BOOST_CLASS_EXPORT_GUID (as in the doc), > > this works > > > perfectly if the derived class is in the main execution, > > i think you should read: > > it works perfectly if *BOOST_CLASS_EXPORT_GUID* is in the main > > execution. > > you can still put your derived class wherever you want ! > > > > > but will give me an > > > exception > > what exception ? > > > > > if the derived class is in the plugin DLL. > > > > > It looks like an issue I've met a few weeks ago. > > After investigation (note may be I'm wrong but I can only report of > my > > understanding which is far > > to be good !) I now believe it is NOT possible > > to scatter such serialization export bits in different places (DLL vs > > executable, DLL vs DLL). > > It is because, as far as I understand the concept, the "export" > > mechanism > > you mentioned is implemented in the DLL object scope (probably using > > some static 'local' dictionary instantiated in the DLL scope or the > > executable scope, depending of the user). > > You can imagine such case: your base class is registered in the DLL > but > > your > > Daughter class is registered at the level of the executable object > > scope > > : thus there is no > > way to make them communicate about their relationship. Both > > dictionaries > > (one per instantiation unit) acts > > in different words and know only one subset of the serializable > classes > > to be used in your executable. > > > > The solution for me was to make sure that ALL my serialization code, > > together with > > the associated export stuff mechanism ,is instantiated in one and > only > > one place: the executable. > > At least, I do not pollute my DLLs with some serialization related > > instantiations > > that may be I won't use in some of my other executables. > > > > In your case, I think you could step back to the previous approach > > where > > all serialization stuff is instantiated in the executable. > > The alternative is to probably to move your xml_archive ser/deser > code > > in some resource implemented in the DLL and promote some reader and > > writer classes for XML archives > > as an element of your DLL, the later being the unique place to safely > > embed the problematic bits. > > I'm afraid there is not intermediate. > > > > You may find this "feature" annoying or even disappointing. > > However, it is not a bug ! It is a conceptual choice made by Robert > for > > the Serialization lib. > > It is not as bad as you could think at a first glance. IMHO it is a > > good > > design not to have > > a central export registration 'manager'. Otherwise, such a beast > would > > encourage developpers to > > add large amount of instantiated serialization/export code in any DLL > > for large collection > > of serializable classes, with some consequence to > > possibly end up with lots of unused serialization code being linked > > for > > nothing. I also think this would break > > the "template" spirit and probably could lead to performance issues > if > > thousands of inherited > > classes from several independant DLLs were registered in one single > > central place. > > > > With the current implementation of the lib, > > users are forced to do a careful analysis of what they need from the > > executable > > in term of base-pointer oriented serialization. They have to manage > > to instantiate the only serialization bits strictly necessary for > their > > I/O. > > The corresponding template code that will be generated is thus > minimal. > > > > I recommend you not to use the *EXPORT* macro in your class header > > file, > > as well as instantiation code > > of the template "serialize" methods of your class. Use some kind of > > .ipp > > files for that to be included > > from your main program when it makes sense, and not by default in > your > > DLL. > > I find this technique rather sane (of course it needs extra care, but > > that does not hurt, isn't it ?). > > Note also that if you don't want to use some "my_serialization.ipp" > > file, you can provide an alternative one, > > with different implementation of the template serialization code. > > > > I hope you find find these comments useful. > > Note I'm not completely sure they make sense in your situation. In > the > > absence of more details, > > it is only a guess, probably not very understandable... sorry for > that. > > Also I'm not sure to understand well the pb. I probably have a rather > > partial view on it. > > > > Hope some gurus will be able to raise the tone of this technical > > debate. > > I would enjoy to read more about > > this topic. > > > > cheers > > > > frc > > -- > > > Forgive me if the problem is too obvious, this is my first time > using > > Boost > > > and I'm still a big noob in c++. > > > > > > Here is my code : > > > > > > IN THE MAIN EXECUTION : > > > > > > Class Base (parent class) : > > > > > > Base.h : > > > #pragma once; > > > #include "boost\serialization\access.hpp" > > > #include <boost\serialization\nvp.hpp> > > > > > > class Base > > > { > > > private: > > > friend class boost::serialization::access; > > > template > > > void serialize(Archive & ar, const unsigned int version){} > > > public: > > > int a, b; > > > Base(); > > > virtual ~Base() > > > { > > > } > > > virtual void func()= 0; // this is an abstract base class > > > } > > > > > > Base.cpp: > > > > > > #include "StdAfx.h" > > > #include "Base.h" > > > > > > Base::Base(){ > > > a=0; > > > b=0; > > > } > > > > > > > > > IN THE DLL (loaded explicitely) > > > > > > Class Plugin (Child Class) : > > > > > > Plugin.h: > > > > > > #pragma once > > > #include "boost\serialization\access.hpp" > > > #include <boost\serialization\nvp.hpp> > > > #include "boost\serialization\export.hpp" > > > #include "Base.h" > > > > > > class Plugin: public Base > > > { > > > private: > > > > > > friend class boost::serialization::access; > > > template > > > void serialize(Archive & ar, const unsigned int version){ > > > ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); > > > ar & BOOST_SERIALIZATION_NVP(a); > > > ar & BOOST_SERIALIZATION_NVP(b); > > > } > > > > > > public: > > > virtual void func(); > > > }; > > > > > > BOOST_CLASS_EXPORT_GUID(Plugin, "Plugin") > > > > > > Plugin.cpp: > > > > > > #include "StdAfx.h" > > > #include "Plugin.h" > > > > > > void Plugin::func(){ > > > a= 5; > > > b= 6; > > > } > > > > > > > > > > > > THE MAIN FUNCTION (IN THE MAIN EXECUTION): > > > > > > ....................................... > > > > > > HINSTANCE hinst= LoadLibrary(L"monDLLdynamique.dll"); > > > if (hinst) > > > { > > > CreatePlugin ctor= (CreatePlugin)GetProcAddress(hinst, > > "CreatePlugin"); > > > Base *test= ctor(); > > > > > > std::ofstream ofs3("FichierPointeursDerivedDLL.xml"); > > > { > > > boost::archive::xml_oarchive oa(ofs3); > > > oa << BOOST_SERIALIZATION_NVP(test); > > > } > > > ofs3.close(); > > > > > > delete test; // calls Plugin's dtor > > > > > > FreeLibrary(hinst); > > > } > > > > > > ............................................ > > > > > > > > > Any help will be very very appreciated !!! > > > Thanks > > > > > > -- > > > View this message in context: > > http://boost.2283326.n4.nabble.com/Boost-Serialization-Problem- > > serializing-derived-class-declared-in-DLL-tp3428913p3428913.html > > > Sent from the Boost - Users mailing list archive at Nabble.com. > > > _______________________________________________ > > > Boost-users mailing list > > > Boost-users_at_[hidden] > > > http://lists.boost.org/mailman/listinfo.cgi/boost-users > > > > > > > > > > > > -- > > François Mauger > > Groupe "Interactions Fondamentales et Nature du Neutrino" > > NEMO-3/SuperNEMO Collaboration > > LPC Caen-CNRS/IN2P3-UCBN-ENSICAEN > > Département de Physique -- Université de Caen Basse-Normandie > > Adresse/address: > > Laboratoire de Physique Corpusculaire de Caen (UMR 6534) > > ENSICAEN > > 6, Boulevard du Marechal Juin > > 14050 CAEN Cedex > > FRANCE > > Courriel/e-mail: mauger_at_[hidden] > > Tél./phone: 02 31 45 25 12 / (+33) 2 31 45 25 12 > > Fax: 02 31 45 25 49 / (+33) 2 31 45 25 49 > > > > > > _______________________________________________ > > Boost-users mailing list > > Boost-users_at_[hidden] > > http://lists.boost.org/mailman/listinfo.cgi/boost-users > _______________________________________________ > Boost-users mailing list > Boost-users_at_[hidden] > http://lists.boost.org/mailman/listinfo.cgi/boost-users
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