boost::serialization - свой архиватор
От: Аноним  
Дата: 26.04.11 06:08
Оценка:
Написал свой архиватор для boost::serialization, с целью а) бинарной переносимости б) контроля над форматом пакета

При попытке использовать сериализацию полиморфных классов, выдает ошибки линковки типа

client.o: In function `~pointer_oserializer':
/usr/local/include/boost/archive/detail/oserializer.hpp:222: undefined reference to `boost::archive::detail::archive_serializer_map<raw_binary_oarchive>::erase(boost::archive::detail::basic_serializer const*)'
client.o: In function `void boost::archive::detail::save_pointer_type<raw_binary_oarchive>::polymorphic::save<base>(raw_binary_oarchive&, base&)':
/usr/local/include/boost/archive/detail/oserializer.hpp:435: undefined reference to `boost::archive::detail::archive_serializer_map<raw_binary_oarchive>::find(boost::serialization::extended_type_info const&)'


При попытке определить недостающие функции все линкуется, но падает по sigfault:
namespace boost {
namespace archive {
namespace detail {

template <>
const basic_serializer * archive_serializer_map<raw_binary_oarchive>::find(const boost::serialization::extended_type_info & type_){}

template <>
bool archive_serializer_map<raw_binary_oarchive>::insert(boost::archive::detail::basic_serializer const*){}

template <>
void archive_serializer_map<raw_binary_oarchive>::erase(boost::archive::detail::basic_serializer const*){}
} } }


Вот минимальный код, на котором воспроизводится проблема:
/*
 * File:   raw_binary_archive.h
 */

#include <boost/archive/binary_oarchive_impl.hpp>
#include <boost/archive/binary_iarchive_impl.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

// include template definitions for base classes used.  Otherwise
// you'll get link failure with undefined symbols
#include <boost/archive/impl/basic_binary_oprimitive.ipp>
#include <boost/archive/impl/basic_binary_iprimitive.ipp>
#include <boost/archive/impl/basic_binary_oarchive.ipp>
#include <boost/archive/impl/basic_binary_iarchive.ipp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/utility/enable_if.hpp>

namespace ba = boost::archive;

class raw_binary_oarchive :
public ba::binary_oarchive_impl<raw_binary_oarchive, std::ostream::char_type,
        std::ostream::traits_type> {

    typedef raw_binary_oarchive derived_t;
    typedef ba::binary_oarchive_impl<raw_binary_oarchive, std::ostream::char_type,
        std::ostream::traits_type> base_t;


public:

    template<class T>
    void save_override(T & t, BOOST_PFTO int) {
        base_t::save_override(t, 0);
    }

    void save_override(const boost::archive::class_name_type & t, int) { }
    void save_override(const boost::archive::library_version_type & t, int) { }
    void save_override(const boost::archive::version_type & t, int) { }
    void save_override(const boost::archive::class_id_type & t, int) { }
    void save_override(const boost::archive::class_id_reference_type & t, int) { }
    void save_override(const boost::archive::class_id_optional_type & t, int) { }
    void save_override(const boost::archive::object_id_type & t, int) { }
    void save_override(const boost::archive::object_reference_type & t, int) { }
    void save_override(const boost::archive::tracking_type & t, int) { }

public:

    raw_binary_oarchive(std::ostream & os, unsigned flags = 0) :
    base_t(os, flags | boost::archive::no_header) { }

    raw_binary_oarchive(std::streambuf & bsb, unsigned int flags = 0) :
    base_t(bsb, flags | boost::archive::no_header) { }
};


#include <boost/serialization/serialization.hpp>
#include <boost/serialization/export.hpp>
#include "raw_binary_archive.h"

struct base {
    uint8_t x;
    base():x(2){}
    virtual ~base(){}

    template<class Archive>
    inline void serialize(Archive & ar, const unsigned int file_version) {
        ar & BOOST_SERIALIZATION_NVP(x);
    }
};

BOOST_SERIALIZATION_ASSUME_ABSTRACT(base)

struct derived_one : public base {
    uint8_t y;
    derived_one():y(11){}

    template<class Archive>
    inline void serialize(Archive & ar, const unsigned int file_version) {
        ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
        ar & BOOST_SERIALIZATION_NVP(y);
    }
};

BOOST_CLASS_EXPORT(base);
BOOST_CLASS_EXPORT(derived_one);

int main() {
    { boost::archive::detail::archive_serializer_map<raw_binary_oarchive> junk; }

    std::ofstream of("test.file");
    raw_binary_oarchive archive(of);
    archive.register_type<derived_one>();
    base* b = new derived_one();

    archive << BOOST_SERIALIZATION_NVP(b);
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.