[serialization] problem using BOOST_CLASS_EXPORT macro in a static library
I have some problems with BOOST_CLASS_EXPORT macro, it
seems that this macro have no effect if i put it in
a separate .cpp file of a static library.
I have a simple class Element that contains a pointer to a
curve that can be of different types (geom2d.hpp).
struct Curve
{
Curve() {};
virtual ~Curve() {};
};
struct Line : public Curve
{
Line(int y = 0): m_y(y) {};
int m_y;
};
typedef boost::shared_ptr< Curve > CurvePtr;
struct Element
{
Element(const CurvePtr & curve):
m_curve(curve) {}
boost::shared_ptr< Curve > m_curve;
};
I would like to be able to serialize Element, so i
wrote a serialize.hpp file (attached) containing code for
serializing those structures.
I also wrote export.cpp using
#include "geom2d.hpp"
#include
The problem is that the exported type is not explicitly referred to in the code so the implemenation doesn't get pulled out of the static library. After all the purpose of using a static library is to make sure that your executable ONLY contains code that it is known (at compile time) to be required. There are a couple of ways to do this. a) include an "export.cpp" which includes all your EXPORT macros b) include them in a DLL and load the DLL at execute time. Or c) include one class/function in your DLL which you KNOW will be referred to at execution time c) use explicit registration of derived types - thereby avoiding EXPORT all together Basically ALL of these methods amount to advising your executable of the types you plan to serialize before you actually serialize them. This can happen automagially in some cases (e.g. c) above) or explicitly. Robert Ramey Renaud Lepere wrote:
I have some problems with BOOST_CLASS_EXPORT macro, it seems that this macro have no effect if i put it in a separate .cpp file of a static library.
I have a simple class Element that contains a pointer to a curve that can be of different types (geom2d.hpp).
struct Curve { Curve() {}; virtual ~Curve() {}; }; struct Line : public Curve { Line(int y = 0): m_y(y) {}; int m_y; };
typedef boost::shared_ptr< Curve > CurvePtr; struct Element { Element(const CurvePtr & curve): m_curve(curve) {} boost::shared_ptr< Curve > m_curve; };
I would like to be able to serialize Element, so i wrote a serialize.hpp file (attached) containing code for serializing those structures.
I also wrote export.cpp using
#include "geom2d.hpp" #include
#include #include "serialize.hpp" #include #include <iostream> BOOST_CLASS_EXPORT(Curve); BOOST_CLASS_EXPORT(Line);
I put the export.cpp file in a library named geom2d, but when trying to serialize my structures using something (attached main.cpp).
CurvePtr c(new Line(10)); const Element e(c); std::ofstream ofs("filename"); { boost::archive::text_oarchive oa(ofs); oa << e; } I received an exception "unregistered class". If i dont put export.cpp in a library but in the same compilation unit as main.cpp, the error disappear (visual studio 8.0 and 9.0).
What is the good way of doing this, should i wrote an export.hpp file containing the macros and include this file in a .cpp of the main compilation unit ?
Thanks,
Renaud
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
BOOST_CLASS_EXPORT relies on global objects' constructors to register
the necessary types, however the C++ standard allows a compiler to
strip away such objects unless they are actually used.
The C++ standard guarantees that all global objects contained in a
compilation unit (a CPP file) are initialized by the time execution
enters a function from that compilation unit. So, if execution never
enters a function from that compilation unit, the compiler is allowed
to deadstrip it.
You have 2 options:
1) tinker with your code to trick the compiler into leaving in (not
deadstripping) the automatic BOOST_CLASS_EXPORT registration (which is
usually possible), or
2) register the classes explicitly (not automatic, but guaranteed to work)
Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode
On Tue, Feb 10, 2009 at 9:19 AM, Renaud Lepere
I have some problems with BOOST_CLASS_EXPORT macro, it seems that this macro have no effect if i put it in a separate .cpp file of a static library.
I have a simple class Element that contains a pointer to a curve that can be of different types (geom2d.hpp).
struct Curve { Curve() {}; virtual ~Curve() {}; }; struct Line : public Curve { Line(int y = 0): m_y(y) {}; int m_y; };
typedef boost::shared_ptr< Curve > CurvePtr; struct Element { Element(const CurvePtr & curve): m_curve(curve) {} boost::shared_ptr< Curve > m_curve; };
I would like to be able to serialize Element, so i wrote a serialize.hpp file (attached) containing code for serializing those structures.
I also wrote export.cpp using
#include "geom2d.hpp" #include
#include #include "serialize.hpp" #include #include <iostream> BOOST_CLASS_EXPORT(Curve); BOOST_CLASS_EXPORT(Line);
I put the export.cpp file in a library named geom2d, but when trying to serialize my structures using something (attached main.cpp).
CurvePtr c(new Line(10)); const Element e(c); std::ofstream ofs("filename"); { boost::archive::text_oarchive oa(ofs); oa << e; } I received an exception "unregistered class". If i dont put export.cpp in a library but in the same compilation unit as main.cpp, the error disappear (visual studio 8.0 and 9.0).
What is the good way of doing this, should i wrote an export.hpp file containing the macros and include this file in a .cpp of the main compilation unit ?
Thanks,
Renaud
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Emil Dotchevski wrote:
BOOST_CLASS_EXPORT relies on global objects' constructors to register the necessary types, however the C++ standard allows a compiler to strip away such objects unless they are actually used.
The C++ standard guarantees that all global objects contained in a compilation unit (a CPP file) are initialized by the time execution enters a function from that compilation unit. So, if execution never enters a function from that compilation unit, the compiler is allowed to deadstrip it.
You have 2 options:
1) tinker with your code to trick the compiler into leaving in (not deadstripping) the automatic BOOST_CLASS_EXPORT registration (which is usually possible), or
2) register the classes explicitly (not automatic, but guaranteed to work)
I can't find 2 in the docs, Can you point me to where to find it? Thanks, Jeff
Hmmm I can't find it either but I know it must be possible. Robert?
Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode
On Wed, Feb 11, 2009 at 6:13 AM, Jeff Flinn
Emil Dotchevski wrote:
BOOST_CLASS_EXPORT relies on global objects' constructors to register the necessary types, however the C++ standard allows a compiler to strip away such objects unless they are actually used.
The C++ standard guarantees that all global objects contained in a compilation unit (a CPP file) are initialized by the time execution enters a function from that compilation unit. So, if execution never enters a function from that compilation unit, the compiler is allowed to deadstrip it.
You have 2 options:
1) tinker with your code to trick the compiler into leaving in (not deadstripping) the automatic BOOST_CLASS_EXPORT registration (which is usually possible), or
2) register the classes explicitly (not automatic, but guaranteed to work)
I can't find 2 in the docs, Can you point me to where to find it?
Thanks, Jeff
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Look in Reference->Archive Concepts->SavingArchiveConcept sa.register_type<T>() sa.register_type(u) Robert Ramey Jeff Flinn wrote:
Emil Dotchevski wrote:
BOOST_CLASS_EXPORT relies on global objects' constructors to register the necessary types, however the C++ standard allows a compiler to strip away such objects unless they are actually used.
The C++ standard guarantees that all global objects contained in a compilation unit (a CPP file) are initialized by the time execution enters a function from that compilation unit. So, if execution never enters a function from that compilation unit, the compiler is allowed to deadstrip it.
You have 2 options:
1) tinker with your code to trick the compiler into leaving in (not deadstripping) the automatic BOOST_CLASS_EXPORT registration (which is usually possible), or
2) register the classes explicitly (not automatic, but guaranteed to work)
I can't find 2 in the docs, Can you point me to where to find it?
Thanks, Jeff
participants (4)
-
Emil Dotchevski
-
Jeff Flinn
-
Renaud Lepere
-
Robert Ramey