Boost logo

Boost Users :

From: Cyril Picat (cpicat_at_[hidden])
Date: 2008-05-29 11:45:49


Hi everybody,

I have just tried a simple example of a class serialization in a DLL and did not
manage to make it work. I have been using Boost serialization since a while but
until now I was putting all the serialization code in the .hpp. By the way
thanks Robert (and Boost) for this great library.

I am using MSVC 8.0 and Boost 1.34.1. I have tried the same with Boost
Serialization 1.36 (head of Boost) without any success.

My test is the following. The class MyClass in declared in a DLL
boost-example.dll built from Example.cpp. A test program Example.t.cpp linked
with boost-example.dll try to serialize MyClass to an XML archive.

The files are the following:

//////// Example.hpp
#if _MSC_VER > 1000
#pragma once
#endif

// Do NOT include any headers after this point #if
(defined(__COMPILING_Example_CPP__) && defined(WIN32)) #define _LIBSPEC
__declspec(dllexport) #else #define _LIBSPEC #endif
    
class _LIBSPEC MyClass
{
 public:
  MyClass();
  
 private:
  friend class boost::serialization::access;
  
  template <class Archive>
  void serialize(Archive & ar, const unsigned int version);
  
  std::string m_str;
  
};

//////// Example.cpp
#include <string>

#include "boost/archive/xml_oarchive.hpp"
#include "boost/archive/xml_iarchive.hpp"

#include "boost/serialization/nvp.hpp"
#include "boost/serialization/export.hpp"

#include "Example.hpp"

using namespace std;

BOOST_CLASS_EXPORT(MyClass); // should explicity instantiate template for
                             // xml_oarchive and xml_iarchive

MyClass::MyClass()
  : m_str("MyClass") {}

template <class Archive>
void MyClass::serialize(Archive & ar, const unsigned int version) {
  ar & BOOST_SERIALIZATION_NVP(m_str);
}

//////// Example.t.cpp
#include <iostream>
#include <fstream>

#include "boost/archive/xml_oarchive.hpp"
#include "boost/serialization/nvp.hpp"

#include "Example.hpp"

using namespace std;

int main(int argc, char* argv[])
{
  MyClass myClass;

  // try to serialize MyClass using an XML archive
  ofstream ofs("myClass.xml");

  if( !ofs ) {
    cout << "ERROR: Could not open myClass.xml for writing";
    return EXIT_FAILURE;
  }
      
  try {
    boost::archive::xml_oarchive oa(ofs);
    
    oa << BOOST_SERIALIZATION_NVP(myClass);
      
  } catch (const std::exception& e) {
    cout << "failed to serialize MyClass with xml_oarchive: " << e.what();
    ofs.setstate(ios::failbit);
  }
  
  return EXIT_SUCCESS;
}

When compiling this, I got an error at link time for Example.t:

Example.t.obj : error LNK2019: unresolved external symbol "private: void __thisc
all MyClass::serialize<class boost::archive::xml_oarchive>(class boost::archive:
:xml_oarchive &,unsigned int)" (??$serialize_at_Vxml_oarchive_at_archive@boost@@@MyCla
ss@@AAEXAAVxml_oarchive_at_archive@boost@@I_at_Z) referenced in function "public: stat
ic void __cdecl boost::serialization::access::serialize<class boost::archive::xm
l_oarchive,class MyClass>(class boost::archive::xml_oarchive &,class MyClass &,u
nsigned int)" (??$serialize_at_Vxml_oarchive_at_archive@boost@@VMyClass@@@access_at_seria
lization_at_boost@@SAXAAVxml_oarchive_at_archive@2_at_AAVMyClass@@I_at_Z)

I have taken a look at boost-example.dll with Dependency Walker and there are
quite a few symbols exported for MyClass and boost::archive::xml_oarchive.

Any clue of what is going on? The strange thing is that I have another more
complex example with an abstract class and derived classes in separate DLLs
where I serialize to the base pointer and everything is compiling and working
fine (both with 1.34.1 and HEAD).

I have read the doc ('Exporting Class Serialization') and have seen in the logs
that a lot have changed regarding export since 1.34.1. In what I have
understood, the fix was concerning cases where the macro BOOST_CLASS_EXPORT() is
used in the .hpp, leading to multiple registrations, and not in the .cpp as I am
doing. Am I right?

By the way, I have noticed a little typo in the doc concerning
void_cast_register. In the doc the proposed syntax is
'boost::serialization::void_cast_register<derived, base>(static_cast<base
*>(NULL), static_cast<derived *>(NULL))' although in my experience the
correct syntax is: 'boost::serialization::void_cast_register<derived,
base>(static_cast<derived*>(NULL),static_cast<base*>(NULL))'

Thanks in advance,

Cyril Picat


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