cereal icon indicating copy to clipboard operation
cereal copied to clipboard

Documentation about StaticObject across DLLs

Open masariello opened this issue 6 years ago • 0 comments

Could we change the Cereal documentation to reflect the below information, please?

I'm talking specifically of the second "Important!" remark at https://uscilab.github.io/cereal/polymorphism.html

The remark says:

If you are building a dynamic library on Windows, registration must occur within the header file. Source file registration will not properly occur outside of the DLL. This issue is not present on Linux or Mac.

This following is also shared by a reply at https://stackoverflow.com/questions/24604304/vs2013-create-several-dll-files-with-different-classes-to-serialize-with-cereal/59413263#59413263

The problem of using CEREAL_REGISTER_TYPE across DLLs can be solved with cereal 1.3.0 (should work with 1.1 too) by having the following statements in an hpp in a DLL at the bottom of a DLL dependency chain. Let's call it core.dll. In that DLL one will have a file called config.hpp with the following traditional macro. CMake will define core_EXPORTS when generating the build scripts for core.dll. This is all very familiar to Windows developers, I'm sure.

#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
#  if defined(core_EXPORTS)
#    define CORE_DECL __declspec(dllexport)
#  else
#    define CORE_DECL __declspec(dllimport)
#  endif
#endif

Then in another export.hpp in core.dll have the following

namespace cereal {
    namespace detail {
        // these declspecs will ensure that the polymorphic loader/saver registrations will
        // all happen against the binding maps in core.dll
        template class CORE_DECL StaticObject<InputBindingMap<PortableBinaryInputArchive>>;
        template class CORE_DECL StaticObject<InputBindingMap<JSONInputArchive>>;
        template class CORE_DECL StaticObject<OutputBindingMap<PortableBinaryOutputArchive>>;
        template class CORE_DECL StaticObject<OutputBindingMap<JSONOutputArchive>>;
        // add similar statements for other archive types as needed
        template class CORE_DECL StaticObject<Versions>;
    } // namespace detail
} // namespace cereal

All other cpp files (no need to include in hpp) in the other dll projects will #include <core/export.hpp> thereby telling the linker to use the cereal StaticObjects in core.dll. If you debug the InputBindingCreator constructor you will notice that every class is now being registered in the same binding map.

Hope this helps. Regards

masariello avatar Dec 20 '19 08:12 masariello