Search code examples
c++c++11polymorphismlibcereal

Issue correctly using CEREAL_REGISTER_DYNAMIC_INIT in C++ Cereal library


I've moved to using a lib file and wanted to make use of CEREAL_REGISTER_DYNAMIC_INIT properly. I don't know if I need to use this, but I noticed an issue with one of my cerealization types not being picked up properly in a separate DLL and thought this might help.

in accountActions.h I have the following at the end of the file:

CEREAL_FORCE_DYNAMIC_INIT(mv_clientactions);

In accountActions.cpp I have the following near the top of the file:

#include "clientActions.h"

#include "cereal/cereal.hpp"
#include "cereal/types/base_class.hpp"
#include "cereal/types/polymorphic.hpp"
#include "cereal/archives/adapters.hpp"

#include "cereal/archives/portable_binary.hpp"
#include "cereal/archives/json.hpp"

CEREAL_REGISTER_TYPE(CreatePlayer);
CEREAL_REGISTER_TYPE(LoginRequest);
CEREAL_REGISTER_TYPE(FindMatchRequest);
CEREAL_REGISTER_TYPE(ExpectedPlayersNoted);
CEREAL_REGISTER_DYNAMIC_INIT(mv_accountactions);

Assume mv_accountactions is just a completely made up string. I don't have any library or dll named that, but figured it is used to link these two units together? Documentation is sparse and I may be using this incorrectly.

The error I'm getting is this:

1> c:\git\bindstone\source\game\networklayer\accountactions.cpp(13): error C2084: function 'void cereal::detail::dynamic_init_dummy_mv_accountactions(void)' already has a body 1> c:\git\bindstone\source\game\networklayer\accountactions.h(127): note: see previous definition of 'dynamic_init_dummy_mv_accountactions'

I've double checked and am not using mv_accountactions anywhere else... I don't know what might cause this or how to resolve it. I'm wondering if I even need the CEREAL_REGISTER_DYNAMIC_INIT, or if there's a safe way to use it in case I do move to a DLL and I'm just misusing it.

Advice would be greatly appreciated.

Issue Opened Here: https://github.com/USCiLab/cereal/issues/523


Solution

  • I seem to have been able to fix this by defining the CEREAL_FORCE_DYNAMIC_INIT with the previously missing CEREAL_DLL_EXPORT

    Before (not working in VS 2017):

    //! Forces dynamic initialization of polymorphic support in a
    //! previously registered source file
    /*! @sa CEREAL_REGISTER_DYNAMIC_INIT
    
        See CEREAL_REGISTER_DYNAMIC_INIT for detailed explanation
        of how this macro should be used.  The name used should
        match that for CEREAL_REGISTER_DYNAMIC_INIT. */
    #define CEREAL_FORCE_DYNAMIC_INIT(LibName)              \
      namespace cereal {                                    \
      namespace detail {                                    \
        void dynamic_init_dummy_##LibName();                \
      } /* end detail */                                    \
      namespace {                                           \
        void dynamic_init_##LibName()                       \
        {                                                   \
          ::cereal::detail::dynamic_init_dummy_##LibName(); \
        }                                                   \
      } } /* end namespaces */
    

    After (Fixed):

    //! Forces dynamic initialization of polymorphic support in a
    //! previously registered source file
    /*! @sa CEREAL_REGISTER_DYNAMIC_INIT
    
        See CEREAL_REGISTER_DYNAMIC_INIT for detailed explanation
        of how this macro should be used.  The name used should
        match that for CEREAL_REGISTER_DYNAMIC_INIT. */
    #define CEREAL_FORCE_DYNAMIC_INIT(LibName)              \
      namespace cereal {                                    \
      namespace detail {                                    \
        void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName();                \
      } /* end detail */                                    \
      namespace {                                           \
        void dynamic_init_##LibName()                       \
        {                                                   \
          ::cereal::detail::dynamic_init_dummy_##LibName(); \
        }                                                   \
      } } /* end namespaces */