Boost logo

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 &lt;boost\serialization\nvp.hpp&gt;
> > >
> > > 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 &lt;boost\serialization\nvp.hpp&gt;
> > > #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