Boost logo

Boost Users :

Subject: Re: [Boost-users] [serialization] Multiply definedsymbol:guid_initializer
From: Robert Ramey (ramey_at_[hidden])
Date: 2009-04-03 14:37:53


Two things are getting mixed up here.

a) The first is not using RTTI. You've used the test as an example and this seems fine to me.

b) You want to serialize a polymorphic derived class through a pointer to it's base class. This
is OK too, but requires special care. The problem is that C++ compile/link will generally not
include code which is not specifically referred to. This occurs when compiling (optimizing out
dead code) and linking - skipping modules not referred to.

To deal with the second, you have "trick" the compiler/linker to not discard your code. There
are a couple of ways to do this.

a) Somewhere in the main module, refer to the derived type in the library. An easy way to
do this is to just create one more function in your code which refers to the code in the library.
Well, its not that easy because the C++ optimiser will usually throw away the whole call
if the result isn't used. You can use the "force_include.hpp" to keep this from happening.

b) You can re-package your library as a DLL. DLLS are different in that the whole DLL
is imported when the application starts up - not just the functions actually referred to.
The "registers" all the "EXPORT"ed functions and things would as advertised.

Sorry it has to be this way. The whole idea of using a library is to automatically
include only that code which the linker detects is actually called. Loading through
a base class pointer explicitly hides this fact so one has to make special effort
of some sort. The only other alternative would be to have the linker import ALL the
code in the library which would defeat the reason for having a library in the first place.

Robert Ramey
  "Robert Dailey" <rcdailey_at_[hidden]> wrote in message news:496954360904030944k1451ee4aob68a0abc8c30a43f_at_mail.gmail.com...
  Besides, it doesn't make sense to have the global function in the first place. I'm already creating instances of the very class I'm exporting via the macro. That alone should be enough to keep the compiler from stripping out the class specializations created by the boost class macros, right? This whole thing is just so confusing... why can't it just work like it is supposed to? I am doing things exactly as they are being done in the test_no_rtti unit test...

  On Fri, Apr 3, 2009 at 11:26 AM, Robert Dailey <rcdailey_at_[hidden]> wrote:

    What?? I see you have a force_serialize_export() function, but how can you guys expect me to mangle my interfaces to get boost::serialization to do its job? So I have to now call arbitrary global functions all over the place? This is unreasonable and unacceptable. There has to be a better way!

    On Fri, Apr 3, 2009 at 11:05 AM, Renaud Lepere <Renaud.Lepere_at_[hidden]> wrote:

      Hello,

      I had a similar problem, you must call a function in the compilation
      unit if you put only the macros in the .cpp if will not work.

      BOOST_CLASS_EXPORT(Curve2);
      BOOST_CLASS_EXPORT(Line2);
      BOOST_CLASS_EXPORT(Circle2);

      /**
       * DO NOT REMOVE THIS FUNCTION
       * 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.
       *
       * BOOST_CLASS_EXPORT is based upon global objects.
       */
      void force_serialize_export();

      ________________________________

             De : boost-users-bounces_at_[hidden] [mailto:boost-users-bounces_at_[hidden]] De la part de Robert Dailey
             Envoyé : vendredi 3 avril 2009 16:56
             À : boost-users_at_[hidden]
             Objet : Re: [Boost-users] [serialization] Multiply defined symbol:guid_initializer

             But I've already tried that, as I said. It fails at runtime with an exception saying "unregistered void cast". I'll test it once more, but I don't expect different results.

             On Thu, Apr 2, 2009 at 10:07 PM, Robert Ramey <ramey_at_[hidden]> wrote:

                     Look at the pimple demo in the examples or test directory. Basically you're getting some things defined twiice.

                     Move the implementation of template< class Archive >
                             void serialize( Archive& archive, unsigned int version ) to the *.cpp
                     and move
                     BOOST_CLASS_EXPORT( rs::StaticText )

                     to the *.cpp file as well. compile that/those *.cpp files and include in the library. This is touched upon in the manual in the part describing EXPORT.

                     Robert Ramey

                             "Robert Dailey" <rcdailey_at_[hidden]> wrote in message news:496954360904021720o79c9c17cs18b1cf3f53da08c_at_mail.gmail.com...
                             Hi,

                             I'm currently trying to polymorphically serialize a class without using RTTI. I'm doing this currently in a file called StaticText.hpp:

                             #ifndef RS_GUI_WIDGETS_STATICTEXT_HPP
                             #define RS_GUI_WIDGETS_STATICTEXT_HPP

                             #include <boost/scoped_ptr.hpp>
                             #include <boost/serialization/access.hpp>
                             #include <boost/serialization/base_object.hpp>
                             #include <boost/serialization/string.hpp>
                             #include <boost/serialization/extended_type_info_no_rtti.hpp>
                             #include <boost/serialization/export.hpp>

                             #include <rs/gui/widgets/Widget.hpp>
                             #include <rs/gui/Text.hpp>

                             namespace rs
                             {
                                 class StaticText : public Widget
                                 {
                                 public:
                                     StaticText( std::string const& text );

                                     void Update();
                                     void Render( RenderSystem& renderer, Camera& camera );
                                     char const* get_key() const;

                                 private:
                                     StaticText() {}

                                     template< class Archive >
                                     void serialize( Archive& archive, unsigned int version )
                                     {
                                         archive & boost::serialization::base_object<Widget>( *this );

                                         std::string text;
                                         archive & text;
                                         m_text.reset( new Text( text ) );
                                     }

                                     boost::scoped_ptr<Text> m_text;

                                     friend class boost::serialization::access;
                                 };
                             }

                             BOOST_CLASS_TYPE_INFO(
                                 rs::StaticText,
                                 extended_type_info_no_rtti<rs::StaticText>
                                 )

                             BOOST_CLASS_EXPORT( rs::StaticText )

                             #endif // RS_GUI_WIDGETS_STATICTEXT_HPP

                             When I compile this into a LIB first, and then link the lib into an EXE, the linker says this (Visual Studio 2008):
                             gui.lib(StaticText.obj) : error LNK2005: "public: static struct boost::archive::detail::guid_initializer<class rs::StaticText> const & const boost::archive::detail::init_guid<class rs::StaticText>::guid_initializer" (?guid_initializer@?$init_guid_at_VStaticText@rs@@@detail_at_archive@boost@@2ABU?$guid_initializer_at_VStaticText@rs@@@234_at_B) already defined in main.obj

                             If I move the 2 macro calls into the StaticText.cpp file, everything compiles/links just fine but I end up getting an exception thrown at runtime that says "unregistered void cast".

                             ________________________________

                                                     _______________________________________________
                             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 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