From: Robert Ramey (ramey_at_[hidden])
Date: 2004-05-05 10:44:40
Martin Ecker wrote:
> > > Is there work under way to fix this and have working DLL builds of
> > > boost::serialization (just as there are DLL builds for, say,
> > > boost::regex)?
> > I have interest in addressing this. I do believe it is addressable
> > too much difficulty but will require some extra care. There also might
> > some restrictions on usage - I don't know yet.
> I looked into this some more and I believe to have found somewhat of
> a solution (albeit a "hacky" one) for the template classes derived from
> extended_type_info. If you don't mind I will send you my current
> boost::serialization code base via private e-mail and you could maybe
> have a look at it. As I wrote above, I do not yet know enough about
> the internal structure of the library, so I can't say for sure if
> my changes broke anything major. In the limited tests I did with the
> demo samples that come with the library everything seemed to work fine
> One thing that I have not yet addressed though is the need for
> extended type info objects to unregister themselves from the
> global registry. This is important when DLLs are loaded, unloaded,
> and then loaded again. I believe this should be quite easy to
> implement. Simply make a call to some unregister function in
> the extended_type_info destructor, similar to the self_register
> call in the constructor.
I have yet to consider the issues related to dynamic loading/unloading of
DLLS. The current system registers things at pre-execution time. I'm not
sure what that means when the object to be registered via construction of a
static object located in a DLL loaded at a subsequent time.
> This actually brings me to another
> question: Why is the self_register call not directly in the
> base class constructor, i.e. in extended_type_info::extended_type_info,
> but rather in the deriving classes?
No particular reason as far as I can see.
> > My intention was the BOOST_CLASS_EXPORT be included in the header file.
> I don't quite understand how this can work reliably. Say, I have two DLLs.
> In one DLL I have class A. A's header file also contains the
> BOOST_CLASS_EXPORT(A) macro. Now a second DLL also needs to use this
> class. Therefore it will include A's header file. This will result
> in a static guid_initializer instance to be created in both DLLs, which
> is unnecessary.
Note that a new static variable instance should created for each archive
included. If no archives are included, then the header with
BOOST_CLASS_EXPORT can be included anywhere any number of times. The actual
restriction should be that it be included only once for a given archive
class. Looking at the code now, I see that its also creating an
extended_type_info instance as well and this will lead to problems with
multiply defined static instances. I believe this can be enhanced to skip
this step of no archives are being included. That doesn't quite do it but
it points the way to improving this.
> Also with the current code it will cause the class'
> extended type info to be registered twice, once in each DLL with a
> different extended type info object each time. I believe my code
> modifications will remedy this though, so it wouldn't matter if
> the registration happened multiple times, but it is still unnecessary.
> The only "proper" way I know of to avoid this is to always use the
> export macros in .cpp files.
I'm coming to this conclusion as well.
> > This would mean code modules would be organized
> > similar to the demo_pimpl example where the implementation of class
> > serialization (invocations of ar << my_class_instance) are in separate
> > modules from the headers rather than inline functions.
> I've looked at that sample, but since we are trying to integrate
> boost::serialization into an existing project, reorganizing all of
> our code is pretty much out of the question.
> We tend to have the serialization code inlined in the header files
> of the class it belongs to. This has so far proven to be good
> for maintenance of the code as well (e.g. when a new member variable
> is added to a class it is harder to forget to also change
> the serialization code, if necessary).
I think it's a mistake to dismiss this idea. I appreciate the ease of
maintenance but in the type of project your working with I think it would be
a) refrain from defining serialize inline in the header file.
b) implement serialize() in the my_class.cpp file for each class.
c) include BOOST_CLASS_EXPORT in each my_class.cpp file
d) instanciate the templates in the class *.cpp file for archive classes you
expect to support. Only the my_class.cpp will included archive class
I believe it is common practice is to have an *.hpp file and a *.cpp file
for each non-trivial class. So I would be surprised to find that much code
reorganization would be required to implement this. I also believe that to
reliably support libraries and DLLs of exported classes, such an
organization will be required. It will also result in much smaller code
with almost no loss of speed. If the code is compiled to a static library,
the executable won't contain any "dead" code. If compiled to a DLL, the code
won't have to be loaded unless it is actually used.
Note that this organization will be required only for those class types
which are serialized through pointers to derived classes. So it may not be
as much as a burden as it might seem.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk