Boost Serialization вызывает неправильный метод сериализации

Я использовал macro пара BOOST_CLASS_EXPORT_KEY(T) для заголовочного файла и BOOST_CLASS_EXPORT_IMPLEMENT(T) для файла реализации, чтобы сериализовать производный класс от указателя базового класса.

(** примечание: я поместил макрос во все заголовки и файлы реализации, которые должны быть сериализованы, включая базовый класс)

Тем не менее, есть странная проблема, с которой я столкнулся при сериализации до определенного класса. У меня проблема в том, что сериализация правильна, когда saving но неправильно когда loading который вызовет другой метод сериализации класса.

ОБНОВЛЕНО: К вашему сведению, после вызова неправильного метода сериализации из другого класса, исключение незарегистрированного класса выброшено. Код только имеет проблемы в binary_archive и работает нормально для text_archive что смущает меня, как я думал, если text_archive тогда сериализация в порядке binary_archive Должен не имеет проблем. Или мне не хватает какой-то особенной разницы, о которой нужно здесь позаботиться.

Фрагмент кода приведен ниже:

К вашему сведению, проблема возникает при попытке десериализации SubModelLayer, SubModelLayer также наследует Node,

template<typename Archive>
void ModelLayer::serialize(Archive & ar, const unsigned int version)
{
    // invoke serialization of the base class 
    ar & boost::serialization::base_object<Node>(*this);
    //this will actually call the 
    //ModelLayerData<_MODEL_LAYER_VERSION_ONE>::serialize
    //for serialization
    serialize_helper(_modelLayerData, ar, version);
}

template<typename Archive>
void ModelLayerData<_MODEL_LAYER_VERSION_ONE>::serialize(Archive & ar)
{
    ar & _xDimension;
    ar & _yDimension;
    ar & _zDimension;

    if (Archive::is_saving::value)
    {
        int dataType = static_cast<int>(_dataType);
        ar & dataType;
        size_t const totalSize = _xDimension*_yDimension*_zDimension;

        switch (_dataType)
        {
        case DataType::UCHAR:
            ar & boost::serialization::make_array<unsigned char>(_imageData.get(), totalSize);
            break;
        case DataType::USHORT:
            ar & boost::serialization::make_array<unsigned short>(_ushortImageData.get(), totalSize);
            break;
        default:
            std::string message = std::string(__FUNCTION__) + " | " + std::string(__FILE__);
            throw ModelLayerException::InvalidDataException(message);
            break;
        }

        size_t subModelLayerCollectionSize = _subModelLayerCollection.size();
        ar & subModelLayerCollectionSize;
        //submodellayer
        for (auto const &key : _subModelLayerCollection)
        {
            SubModelLayer *subModelLayer = key.second.get();
            ar & subModelLayer; //saving is calling the correct serialization method in SubModelLayer
        }
    }
    if (Archive::is_loading::value) //loading
    {
        int dataType;
        ar & dataType;
        _dataType = static_cast<DataType>(dataType);
        try
        {
            size_t const totalSize = _xDimension*_yDimension*_zDimension;
            switch (_dataType)
            {
            case DataType::UCHAR:
                _imageData.reset(new unsigned char[totalSize]);
                ar & boost::serialization::make_array<unsigned char>(_imageData.get(), totalSize);
                break;
            case DataType::USHORT:
                _ushortImageData.reset(new unsigned short[totalSize]);
                ar & boost::serialization::make_array<unsigned short>(_ushortImageData.get(), totalSize);
                break;
            default:
                std::string message = std::string(__FUNCTION__) + " | " + std::string(__FILE__);
                throw ModelLayerException::InvalidDataException(message);
                break;
            }
            int subModelLayerCollectionSize;
            ar & subModelLayerCollectionSize;
            for (size_t i = 0; i < subModelLayerCollectionSize; i++)
            {
                std::string timestamp;
                std::unique_ptr<SubModelLayer> subModelLayer;
                SubModelLayer * rawSubModelLayer = new SubModelLayer();
                //problem happens here
                ar & rawSubModelLayer; //loading is calling the wrong serialization method which is located in another class
                subModelLayer.reset(rawSubModelLayer);
                timestamp = subModelLayer->getTimestamp();
                _subModelLayerCollection.insert(std::map<std::string, std::unique_ptr<SubModelLayer>>::value_type(timestamp, std::move(subModelLayer)));
                switch (_dataType)
                {
                case DataType::UCHAR:
                    _subModelLayerCollection.at(timestamp)->setImageData(_imageData.get(), _xDimension, _yDimension, _zDimension);
                    break;
                case DataType::USHORT:
                    _subModelLayerCollection.at(timestamp)->setImageData(_ushortImageData.get(), _xDimension, _yDimension, _zDimension);
                    break;
                default:
                    std::string message = std::string(__FUNCTION__) + " | " + std::string(__FILE__);
                    throw ModelLayerException::InvalidDataException(message);
                    break;
                }
            }
        }
        catch (const std::exception& ex)
        {
            std::string message = std::string(ex.what()) + " " + std::string(__FUNCTION__) + " | " + std::string(__FILE__);
            throw ModelLayerException::AllocateImageDataException(message);
        }
    }
}

Я подозревал, что при регистрации производного класса могут возникнуть проблемы из-за неправильного использования API.

Мой пример выходного файла, как показано ниже, в котором я не вижу, что есть строковый идентификатор класса, который говорит Boost, какой класс для создания и десериализации.

22 serialization::archive 13 0 1 1
0 0 1 5.714890957e+000 -1.402821732e+001 1.363411617e+001 5.255104303e-001 1.317463517e-001 -1.736424565e-001 8.223928213e-001 1.000000000e+000 1.410727501e+001 2.772170639e+001 2.090770340e+001 7.853981853e-001 1 0 2 1 1
1 1 0 3 1 1
2 10 10 10 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 4 4 1 1
3 10 10 10 0 0 0 10 10 10 0 4
4 10 10 10 0 0 0 10 10 10 0 4
5 10 10 10 0 0 0 10 10 10 0 4
6 10 10 10 0 0 0 10 10 10 0 0 -1.00000000000000000e+000 1.00000000000000000e+000

Но небольшой пример, имитирующий мою структуру классов в coliru, создает вывод, содержащий идентификатор для классов.

http://coliru.stacked-crooked.com/a/567d455fb020734d

ОБНОВЛЕНИЕ: прикреплен заголовок и источник SubModelLayer, а также источник SubModelLayerData.

SubModelLayer.hpp

//SubModelLayer.hpp    
static const unsigned _SUB_MODEL_LAYER_DATA_VERSION = 1;
    static const unsigned _SUB_MODEL_LAYER_DATA_CURRENT_VERSION = _SUB_MODEL_LAYER_DATA_VERSION;

template<unsigned version>
class SubModelLayerData;

template<>
class SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION> 
    : public Serializable, Setup
{
public:
    //No OIV object initialization should be done in constructor
    SubModelLayerData();
    ~SubModelLayerData();

    void setup();

    // Inherited via Serializable
    virtual void synchronize();

    template<typename Archive>
    void serialize(Archive & ar);

    int _xDimension;
    int _yDimension;
    int _zDimension;
    void *_data;
};

class SubModelLayer : public Node
{
public:
    SubModelLayer();
    ~SubModelLayer();
    // Inherited via Node
    virtual void synchronize() override;
    void setImageData(unsigned short * imageData, int const xDimension, int const yDimension, int const zDimension);
    void setImageData(unsigned char * imageData, int const xDimension, int const yDimension, int const zDimension);

private:
    friend class boost::serialization::access;
    template<typename Archive>
    void serialize(Archive & ar, const unsigned int version);

    // Inherited via Node
    virtual void setup() override;
    void renderSubModelLayer(int dataByteSize);

    //current version of sceneData
    SubModelLayerData<_SUB_MODEL_LAYER_DATA_CURRENT_VERSION> _subModelLayerData;
};

BOOST_CLASS_VERSION(SubModelLayer, _SUB_MODEL_LAYER_DATA_CURRENT_VERSION);
BOOST_CLASS_EXPORT_KEY(SubModelLayer);

SubModelLayer.cpp

//SubModelLayer.cpp
template void SubModelLayer::serialize(boost::archive::text_iarchive & ar, const unsigned int version);
template void SubModelLayer::serialize(boost::archive::text_oarchive & ar, const unsigned int version);
template void SubModelLayer::serialize(boost::archive::binary_iarchive & ar, const unsigned int version);
template void SubModelLayer::serialize(boost::archive::binary_oarchive & ar, const unsigned int version);


SubModelLayer::SubModelLayer()
    : Node(VArtObjectTypeID::SUBMODEL_LAYER)
{
    setup();
}

SubModelLayer::~SubModelLayer()
{
}

void SubModelLayer::setup()
{
    _subModelLayerData._root = getGroup();
    _subModelLayerData.setup();
    _subModelLayerData._root->setUserData(this);
}

template<typename Archive>
void SubModelLayer::serialize(Archive & ar, const unsigned int version)
{
    // invoke serialization of the base class
    ar & boost::serialization::base_object<Node>(*this);
    serialize_helper(_subModelLayerData, ar, version);
}

void SubModelLayer::synchronize()
{
    _subModelLayerData.synchronize();
}

void SubModelLayer::setImageData(unsigned short * imageData, int const xDimension, int const yDimension, int const zDimension)
{
    _subModelLayerData._data = imageData;
    _subModelLayerData._xDimension = xDimension;
    _subModelLayerData._yDimension = yDimension;
    _subModelLayerData._zDimension = zDimension;

    renderSubModelLayer(_UNSIGNED_SHORT_BYTE_SIZE);
}

void SubModelLayer::setImageData(unsigned char * imageData, int const xDimension, int const yDimension, int const zDimension)
{
    _subModelLayerData._data = imageData;
    _subModelLayerData._xDimension = xDimension;
    _subModelLayerData._yDimension = yDimension;
    _subModelLayerData._zDimension = zDimension;
    renderSubModelLayer(_UNSIGNED_CHAR_BYTE_SIZE);
}

BOOST_CLASS_EXPORT_IMPLEMENT(SubModelLayer);

SubModelLayerData.cpp

//SubModelLayerData.cpp
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::text_iarchive & ar);
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::text_oarchive & ar);
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::binary_iarchive & ar);
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::binary_oarchive & ar);

SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::SubModelLayerData()
{
    _xDimension = 0;
    _yDimension = 0;
    _zDimension = 0;
}

template<typename Archive>
void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(Archive & ar)
{
    ar & _xDimension;
    ar & _yDimension;
    ar & _zDimension;
}

SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::~SubModelLayerData()
{
}

void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::synchronize()
{
}

void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::setup()
{
}

ОБНОВЛЕНИЕ: Кстати, я использую код ниже, чтобы загрузить и сохранить двоичный файл

Scene * scene;
{
    std::ifstream file(projectName, std::ios::binary);
    boost::archive::binary_iarchive ia{ file };
    ia >> scene;
}
return scene;

{
    std::ofstream ofs(projectName, std::ios::binary);
    boost::archive::binary_oarchive binaryArchive(ofs);
    binaryArchive << scene;
}

ОБНОВЛЕНО: стек вызовов показывает вызов text_archive в binary_archive десериализации.

Фрагмент кода библиотеки Boost Serialization, который я не понимаю, проблема возникает при выполнении после if(newbpis_ptr != bpis_ptr), Нарушаю ли я что-либо, что может привести к неудаче десериализации. И наконец, исключение, выбрасываемое после этого метода Unregistered Class,

template<class Tptr>
static void invoke(Archive & ar, Tptr & t){
    check_load(*t);
    const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t);
    const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
        // note major hack here !!!
        // I tried every way to convert Tptr &t (where Tptr might
        // include const) to void * &.  This is the only way
        // I could make it work. RR
        (void * & )t,
        bpis_ptr,
        find
    );
    // if the pointer isn't that of the base class
    if(newbpis_ptr != bpis_ptr){
        t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
    }
}

0 ответов

Другие вопросы по тегам