[BOOST_CLASS_EXPORT+export.hpp] multiple link error - gcc3.4

Hi out there We have got folowing problem: ------------------------------------------------------ ***TcpEndpoint.h*** ... #include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> class TcpEndpoint : public I_Endpoint { ... }; #include <boost/serialization/export.hpp> BOOST_CLASS_EXPORT_GUID(RCF::TcpEndpoint, "RCF::TcpEndpoint") ------------------------------------------------------- ------------------------------------------------------ ***a.cpp*** ... #include "./TcpEndpoint.hpp" ... ------------------------------------------------------ ***b.cpp*** ... #include "./TcpEndpoint.hpp" ... ------------------------------------------------------ ***c.cpp*** ... #include "./TcpEndpoint.hpp" ... the result of the linker is: b.o(.bss+0x7b): multiple definition of `boost::archive::detail::guid_initializer<RCF::TcpEndpoint>::instance' a.o(.bss+0x0): first defined here c.o(.bss+0x7b): multiple definition of `boost::archive::detail::guid_initializer<RCF::TcpEndpoint>::instance' a.o(.bss+0x0): first defined here In our structure we ave ONE file containing ALL "BOOST_CLASS_EXPORT_GUID" for derived classes and that works fine till the third party lib also has the BOOST_CLASS_EXPORT_GUID macro inside. All in all we want to have someting like that: "A.h" #inlcude "archive_files_and_export.h" class A : public Base {}; BOOST_CLASS_EXPORT_GUID(A, "A") "B.h" #inlcude "archive_files_and_export.h" class B : public Base {}; BOOST_CLASS_EXPORT_GUID(B, "B") "C.h" #inlcude "archive_files_and_export.h" class C : public Base {}; BOOST_CLASS_EXPORT_GUID(C, "C") "main.cpp" #inlcude "A.h" #inlcude "B.h" #inlcude "C.h" int main() {...} ______________________________________ iRMB - Institute for Computational Modeling in Civil Engineering TU Braunschweig Pockelsstr. 3 (9th Floor) D-38106, Braunschweig, Germany phone +49 531/391-7595 fax +49 531/391-7599 email freud@irmb.tu-bs.de <mailto:freud@irmb.tu-bs.de> web www.irmb.tu-bs.de <http://www.irmb.tu-bs.de/>

I would recommend re-organizing the code slightly as below. ***TcpEndpoint.h*** ... // remove archive headers as they are not an attribute of the class TcpEndpint class TcpEndpoint : public I_Endpoint { ... }; #include <boost/serialization/export.hpp> BOOST_CLASS_EXPORT_GUID(RCF::TcpEndpoint, "RCF::TcpEndpoint")
------------------------------------------------------ ***a.cpp*** ... #include "./TcpEndpoint.hpp" ... ------------------------------------------------------ ***b.cpp*** ... #include "./TcpEndpoint.hpp" ...
------------------------------------------------------ ***c.cpp*** ... #include "./TcpEndpoint.hpp" ...
"A.h" #include <boost/serialization/export.hpp> class A : public Base {}; BOOST_CLASS_EXPORT_GUID(A, "A")
.... "main.cpp" #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #inlcude "A.h" #inlcude "B.h" #inlcude "C.h"
int main() {...}
This should do it. To summarize. EXPORT should be considered an attribute of the class so it can/should be in the class header. #include <...archive.hpp> is not an attribute of the class so it should NOT be in the class header. It is used to emit code for each EXPORT ed type for each archive used. So the combination of and exported type and and archive should be in one and only one module. If you want to encapsulate the serialization code - e.g. you're making a library of all the code for all the types, make a module: a.cpp #include <boost/serialization/text_oarchive.hpp> #include <boost/serialization/text_iarchive.hpp> ...// other archive types here. #include "a.hpp" // includes EXPORT template<class Archive> void a:serialize(Archive ar, const unsigned int version){ ar & ..; .... } Now you'll have the serialization code generated for type a and related to its export key. Note that the code will be generated regardless of whether its called or not. SOOOO I would recommend that you organize your application as a library of modules. One module for each non-trivial type you use. The then link your main module against the library. This will get you what you want, produce the smallest usable executables, and minimize compile and link time. Good Luck Robert Ramey
participants (2)
-
Robert Ramey
-
Sören Freudiger