[serialization] polymorphic archives in dlls and pointer to derived problems

I'm having a lot of trouble getting serialization of derived classes
through a base pointer working across dlls. I have the following:
DLL (data_types.dll) code:
stdafx.h:
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff
from Windows headers
// Windows Header Files:
#include

Kolb, Jeremy wrote:
I'm having a lot of trouble getting serialization of derived classes through a base pointer working across dlls.
Take a look at dll_polymorphic_derived2 in the serialization test directory. The suggested changes are as follows: I have the following:
DLL (data_types.dll) code:
// delete global includes
stdafx.h: #pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: #include
// base doesn't have to be exported
Base.h: #pragma once class __declspec(dllexport) Base { friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version);
public: Base() {} virtual ~Base() {} int i; };
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Base); // Doesn't make a difference.
// base serialization needs to be instantiated for all archives to be used
Base.cpp: #include "stdafx.h" #include "Base.h"
template<class Archive> void Base::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_NVP(i); }
// instantiate for the "real" archives used - that is polymorphic_text_iarchive, etc. // note that I don't believe that this should be necessary for abstract base class Base. // So first try totally excluding this.
template void __declspec(dllexport) Base::serialize(boost::archive::polymorphic_xml_iarchive& ar, const unsigned int version); template void __declspec(dllexport) Base::serialize(boost::archive::polymorphic_xml_oarchive& ar, const unsigned int version);
// be sure to include any other archives which might be used (text, binary, etc) // Derived classes MUST be exported.
Derived.h: #include "Base.h"
class __declspec(dllexport) Derived : public Base { friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version);
public: Derived() {} Derived(int num) : j(num) {} int j; };
BOOST_CLASS_EXPORT_KEY(Derived);
Derived.cpp: #include "stdafx.h" #include "Derived.h"
template<class Archive> void Derived::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); ar & BOOST_SERIALIZATION_NVP(j); }
BOOST_CLASS_EXPORT_IMPLEMENT(Derived);
// instantiate for the "real" archives used - that is polymorphic_xml_iarchive, etc.
template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_xml_iarchive& ar, const unsigned int version); template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_xml_oarchive& ar, const unsigned int version);
My exe links against the DLL and contains the following:
// should run
#include "stdafx.h" #include "boost/archive/polymorphic_xml_iarchive.hpp" #include "boost/archive/polymorphic_xml_oarchive.hpp"
#include "data_types/Derived.h" #include <fstream>
int _tmain(int argc, _TCHAR* argv[]) { std::ofstream f("c:\\test.xml"); boost::archive::polymorphic_xml_oarchive xml(f);
Base* b = new Derived(123); xml & BOOST_SERIALIZATION_NVP(b);
delete b;
return 0; }
Robert Ramey

Thanks for the help but I don't quite follow:
A) Isn't the point of using the polymorphic types is to avoid
instantiating all the types explicitly (at the cost of
performance/virtual function calls)?
Anyway I can't seem to instantiate the polymorphic_xml_oarchive
explicitly without getting linker errors:
#include "boost/archive/polymorphic_xml_oarchive.hpp"
template void __declspec(dllexport)
Base::serialize(boost::archive::polymorphic_xml_oarchive& ar, const
unsigned int version);
BOOST_CLASS_EXPORT_IMPLEMENT(Base);
1>Base.obj : error LNK2019: unresolved external symbol "public: static
bool __cdecl boost::archive::detail::archive_serializer_map
::insert(class boost::archive::detail::basic_serializer const *)" (?insert@?$archive_serializer_map@V?$polymorphic_oarchive_route@V?$xml_o archive_impl@Vxml_oarchive@archive@boost@@@archive@boost@@@detail@archiv e@boost@@@detail@archive@boost@@SA_NPBVbasic_serializer@234@@Z) referenced in function "public: __thiscall boost::archive::detail::pointer_oserializer
::pointer_oserializer (void)" (??0?$pointer_oserializer@V?$polymorphic_oarchive_route@V?$xml_oarchive_ impl@Vxml_oarchive@archive@boost@@@archive@boost@@@detail@archive@boost@ @VBase@@@detail@archive@boost@@QAE@XZ) 1>Base.obj : error LNK2019: unresolved external symbol "public: static void __cdecl boost::archive::detail::archive_serializer_map ::erase(class boost::archive::detail::basic_serializer const *)" (?erase@?$archive_serializer_map@V?$polymorphic_oarchive_route@V?$xml_oa rchive_impl@Vxml_oarchive@archive@boost@@@archive@boost@@@detail@archive @boost@@@detail@archive@boost@@SAXPBVbasic_serializer@234@@Z) referenced in function "public: __thiscall boost::archive::detail::pointer_oserializer ::~pointer_oserializer (void)" (??1?$pointer_oserializer@V?$polymorphic_oarchive_route@V?$xml_oarchive_ impl@Vxml_oarchive@archive@boost@@@archive@boost@@@detail@archive@boost@ @VBase@@@detail@archive@boost@@QAE@XZ)
B) I do not see a dll_polymorphic_derived2 test in 1.44 (which is what I'm using) or trunk. I do see a polymorphic_derived2.cpp but I don't see anything obviously wrong with what that has vs what my file has. Note that I'm definitely getting into guid_initializer<Derived>::export_guid() in the DLL. Can I attach files to the list? I have a vs2008 project that I can post. Thanks. Jeremy -----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Robert Ramey Sent: Tuesday, January 04, 2011 1:29 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [serialization] polymorphic archives in dllsandpointer to derived problems Kolb, Jeremy wrote:
I'm having a lot of trouble getting serialization of derived classes through a base pointer working across dlls.
Take a look at dll_polymorphic_derived2 in the serialization test directory. The suggested changes are as follows: I have the following:
DLL (data_types.dll) code:
// delete global includes
stdafx.h: #pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: #include
// base doesn't have to be exported
Base.h: #pragma once class __declspec(dllexport) Base { friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version);
public: Base() {} virtual ~Base() {} int i; };
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Base); // Doesn't make a difference.
// base serialization needs to be instantiated for all archives to be used
Base.cpp: #include "stdafx.h" #include "Base.h"
template<class Archive> void Base::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_NVP(i); }
// instantiate for the "real" archives used - that is polymorphic_text_iarchive, etc. // note that I don't believe that this should be necessary for abstract base class Base. // So first try totally excluding this.
template void __declspec(dllexport) Base::serialize(boost::archive::polymorphic_xml_iarchive& ar, const unsigned int version); template void __declspec(dllexport) Base::serialize(boost::archive::polymorphic_xml_oarchive& ar, const unsigned int version);
// be sure to include any other archives which might be used (text, binary, etc) // Derived classes MUST be exported.
Derived.h: #include "Base.h"
class __declspec(dllexport) Derived : public Base { friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version);
public: Derived() {} Derived(int num) : j(num) {} int j; };
BOOST_CLASS_EXPORT_KEY(Derived);
Derived.cpp: #include "stdafx.h" #include "Derived.h"
template<class Archive> void Derived::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); ar & BOOST_SERIALIZATION_NVP(j); }
BOOST_CLASS_EXPORT_IMPLEMENT(Derived);
// instantiate for the "real" archives used - that is polymorphic_xml_iarchive, etc.
template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_xml_iarchive& ar, const unsigned int version); template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_xml_oarchive& ar, const unsigned int version);
My exe links against the DLL and contains the following:
// should run
#include "stdafx.h" #include "boost/archive/polymorphic_xml_iarchive.hpp" #include "boost/archive/polymorphic_xml_oarchive.hpp"
#include "data_types/Derived.h" #include <fstream>
int _tmain(int argc, _TCHAR* argv[]) { std::ofstream f("c:\\test.xml"); boost::archive::polymorphic_xml_oarchive xml(f);
Base* b = new Derived(123); xml & BOOST_SERIALIZATION_NVP(b);
delete b;
return 0; }
Robert Ramey _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Kolb, Jeremy wrote:
Thanks for the help but I don't quite follow:
A) Isn't the point of using the polymorphic types is to avoid instantiating all the types explicitly (at the cost of performance/virtual function calls)?
assuming we're talking about polymorphic_?archive here. Now I think about it, I think I gave wrong advice. The correct thing would be to instantiate polymorphic_iarchive and polymorphic_oarchive when creating the DLL. which is what I think you did. BUT you should also make sure these archive types are used by making the following changes:
int _tmain(int argc, _TCHAR* argv[]) { std::ofstream f("c:\\test.xml"); // note creation of derived type of archive asigned to the base type of archive !! boost::archive::polymorphic_oarchive & xml = boost::archive::polymorphic_xml_oarchive(f);
Base* b = new Derived(123); // now serialization should proceed through polimorphic_oarchive interface xml & BOOST_SERIALIZATION_NVP(b);
delete b;
return 0; }
Robert Ramey

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Robert Ramey Sent: Tuesday, January 04, 2011 4:20 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [serialization] polymorphic archivesindllsandpointer to derived problems
int _tmain(int argc, _TCHAR* argv[]) { std::ofstream f("c:\\test.xml");
boost::archive::polymorphic_oarchive & xml = boost::archive::polymorphic_xml_oarchive(f);
Base* b = new Derived(123);
// now serialization should proceed through
// note creation of derived type of archive asigned to the base type of archive !! polimorphic_oarchive interface
xml & BOOST_SERIALIZATION_NVP(b);
delete b;
return 0; }
Oops: realized I was top posting. Unfortunately the above doesn't work. It's the same problem. While the classes are registering with the DLL I don't think the executable is looking in the right place. I tried to pull the export.hpp file out of the executable thinking that might do it but it didn't help.

Double check this to see if this helps. Robert Ramey Derived.cpp: #include "Derived.h" #include "boost/serialization/nvp.hpp" #include "boost/serialization/nvp.hpp" // make sure these are included BEFORE the EXPORT below. // code is intantiatiated only for archives already "seen" #include "boost/archive/polymorphic_iarchive.hpp" #include "boost/archive/polymorphic_oarchive.hpp" template<class Archive> void Derived::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); ar & BOOST_SERIALIZATION_NVP(j); } BOOST_CLASS_EXPORT_IMPLEMENT(Derived); template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_iarchive& ar, const unsigned int version); template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_oarchive& ar, const unsigned int version);

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Robert Ramey Sent: Tuesday, January 04, 2011 11:54 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [serialization]polymorphicarchivesindllsandpointer to derived problems
Double check this to see if this helps.
Robert Ramey
Derived.cpp:
#include "Derived.h"
#include "boost/serialization/nvp.hpp" #include "boost/serialization/nvp.hpp"
// make sure these are included BEFORE the EXPORT below. // code is intantiatiated only for archives already "seen"
#include "boost/archive/polymorphic_iarchive.hpp" #include "boost/archive/polymorphic_oarchive.hpp"
template<class Archive> void Derived::serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); ar & BOOST_SERIALIZATION_NVP(j); }
BOOST_CLASS_EXPORT_IMPLEMENT(Derived); template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_iarchive& ar, const unsigned int version); template void __declspec(dllexport) Derived::serialize(boost::archive::polymorphic_oarchive& ar, const unsigned int version);
That doesn't help either. I've attached a zip of my visual studio solution so you can see what I've done (it's right before this change but it should be equivalent). Jeremy

Kolb, Jeremy wrote:
That doesn't help either. I've attached a zip of my visual studio solution so you can see what I've done (it's right before this change but it should be equivalent).
Jeremy
I
a) downloaded your zip file
b) opened up the solution
c) commented out extraneious includes and other side issues
d) tweaked your project according to my previous advice
e) tweekd the project some more to adjust for differences in path names
f) tweeked the project some more to adjust for other changes
g) added some predefined constants so that autolib functionality works
h) built and ran the project without problems.
Note that I defined some constants related auto-linking DLLs.
So, the whole thing boils down to getting all the project settings right.
I don't mean to suggest that this is trivial. The property page setup
used by the VC IDE is very convenient, but like all such systems
properties have non-obvious side effects which sometimes make
it extremely difficult to make a connection between the problem
and the fix.
of course it doesn't help that C++ standards (as far as I know)
seem to leave unaddressed issues regarding runtime linking (DLLS).
I wish there were a general solution but I don't know of one
other than resigning oneself to picking through all the pages
and setting up all the source "just right".
Robert Ramey
begin 666 s.zip
M4$L#! H``````(!])CX````````````````/````OLM
?QY?XB>X<(W\P6?J],GVQ*.1+]!5=?XDKGP,ZT`%ZI
MD_+GI_5;.^SOGM(>CZ[[]L#-5?+WTG255Z;SG\]_AZ2YJEO8)862\%_"?@$M
MD)7_R/]@SM^W7_\*:?>\HA901_B_D/R9GDIP=,T*D46^+?6B3=M;A7M+_:PG
M9'G6^MDO7:CWK/>FM.;%Z7P&/F@I^
9A
MVDF)M)L+8V^MBSG.]NC&<>1C!.!R.]./W^C"+O:M[8RG!C4VNO=):8F^M-(\
M-<>FO#@CG<>%\G\B]8]P6;\^%=Y_"S%5Q1,6\V-Z7UC_%7\##ON#F0EKNGC*
MR50
3MU,3S"3WB%FN.'K%KFIT$'CM*\\U1
M##ZBM5P7*<:N[23-5Y\$?J
U_O"]6

Robert, I see your reply on boost-users but for some reason it didn't make it back to my mail program so I can't look at the code. Can you resend that zip file so I can compare it with what I have? I guess I don't understand why what I had originally doesn't work. I would expect that simply exporting the key in the header and implementation in the cpp and making sure that they are visible from the DLL would have been enough: the documentation certainly suggests that it's so (unless I'm misreading it). I'm also concerned that the auto-linking stuff isn't working... that doesn't make any sense to me. Thanks for the help, Jeremy

Kolb, Jeremy wrote:
Robert,
I see your reply on boost-users but for some reason it didn't make it back to my mail program so I can't look at the code. Can you resend that zip file so I can compare it with what I have?
I guess I don't understand why what I had originally doesn't work. I would expect that simply exporting the key in the header and implementation in the cpp and making sure that they are visible from the DLL would have been enough: the documentation certainly suggests that it's so (unless I'm misreading it).
I'm also concerned that the auto-linking stuff isn't working... that doesn't make any sense to me.
Thanks for the help, Jeremy
I've attached the zip file here (again?)
Robert Ramey
begin 666 s.zip
M4$L#! H``````(!])CX````````````````/````OLM
?QY?XB>X<(W\P6?J],GVQ*.1+]!5=?XDKGP,ZT`%ZI
MD_+GI_5;.^SOGM(>CZ[[]L#-5?+WTG255Z;SG\]_AZ2YJEO8)862\%_"?@$M
MD)7_R/]@SM^W7_\*:?>\HA901_B_D/R9GDIP=,T*D46^+?6B3=M;A7M+_:PG
M9'G6^MDO7:CWK/>FM.;%Z7P&/F@I^
9A
MVDF)M)L+8V^MBSG.]NC&<>1C!.!R.]./W^C"+O:M[8RG!C4VNO=):8F^M-(\
M-<>FO#@CG<>%\G\B]8]P6;\^%=Y_"S%5Q1,6\V-Z7UC_%7\##ON#F0EKNGC*
MR50
3MU,3S"3WB%FN.'K%KFIT$'CM*\\U1
M##ZBM5P7*<:N[23-5Y\$?J
U_O"]6

I think it's the zip file... maybe naming it .zi_ would get it through?
-----Original Message----- From: Kolb, Jeremy Sent: Friday, January 07, 2011 3:01 PM To: 'boost-users@lists.boost.org' Subject: RE: [Boost-users] [serialization]polymorphicarchivesindllsandpointer to derived problems
Robert,
I see your reply on boost-users but for some reason it didn't make it back to my mail program so I can't look at the code. Can you resend that zip file so I can compare it with what I have?
I guess I don't understand why what I had originally doesn't work. I would expect that simply exporting the key in the header and implementation in the cpp and making sure that they are visible from the DLL would have been enough: the documentation certainly suggests that it's so (unless I'm misreading it).
I'm also concerned that the auto-linking stuff isn't working... that doesn't make any sense to me.
Thanks for the help, Jeremy
participants (2)
-
Kolb, Jeremy
-
Robert Ramey