Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 扩展boost序列化_C++_Serialization_Boost Serialization - Fatal编程技术网

C++ 扩展boost序列化

C++ 扩展boost序列化,c++,serialization,boost-serialization,C++,Serialization,Boost Serialization,我正在尝试为移动设备的网络视频游戏设置多用途序列化。因为它是联网的,在初始连接期间,我需要序列化游戏状态的所有数据,但是,一旦游戏进行中,我只需要序列化某些更改。boost序列化库中的save和load方法只有一个版本号作为参数。我希望能够做的是有更多的参数,这样我就可以更改保存和加载的条件,而不仅仅是基于版本号 下面是普通boost序列化save方法当前的样子: template<class Archive> void save(Archive& ar, const un

我正在尝试为移动设备的网络视频游戏设置多用途序列化。因为它是联网的,在初始连接期间,我需要序列化游戏状态的所有数据,但是,一旦游戏进行中,我只需要序列化某些更改。boost序列化库中的save和load方法只有一个版本号作为参数。我希望能够做的是有更多的参数,这样我就可以更改保存和加载的条件,而不仅仅是基于版本号

下面是普通boost序列化
save
方法当前的样子:

template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
    // Serialize stuff here
}

我只想序列化
SomeClass
,然后让它流到
Bar
,但在这种情况下,它是第三方库/引擎的一部分,我不能修改它。提升序列化是否允许我以这种方式序列化和反序列化?

编辑:下面添加了新答案以解决实际问题

您的问题意味着您重复反序列化到同一对象。这是间接的,如果是干净的或没有。例如,如果你有一个棋盘,你会想 同步棋子的初始位置(从上次保存的游戏继续)。为了在玩游戏时传达动作,最好发送单个动作 作为单独的对象(接收后应用于board对象),而不是传输整个board对象,后者仅传输已“初始化”的更改内容。 这样,您可以先验证输入,然后忽略无效移动。不管怎样,我只是想提一下,让我们继续

如果您有一个可以多次同步的对象,其中的成员数据只需要传输一次,则让该对象决定是否已“初始化” (因此,如果它需要传输所有内容或仅传输一个子集),则使用标志(未序列化)

然后,您可以检查对象序列化代码中的标志,就像在您发布的代码中一样(除了标志不是序列化方法的参数, 而是要反序列化的对象的成员变量)。如果设置了标志,则对所有内容进行反序列化并重置标志。客户端和服务器必须具有相同的标志状态,否则序列化将中断

或者,您可以首先序列化该标志,以告知接收方必须如何执行反序列化(例如,每个成员数据组一位)

请记住,反序列化必须与序列化匹配;必须按照序列化的顺序提取相同的对象

但是,您可以序列化多态类,因为它们通过类层次结构中与反序列化相同的级别进行序列化 (如有疑问,请在发送时强制转换到基指针,并通过基指针进行反序列化)

关于你的第二个问题,你要找的是。 非侵入式序列化调用独立函数并将要序列化的对象作为参数传递(这就是std::vector和boost::shared_ptr的序列化方式)。 您可以使用
BOOST\u SERIALIZATION\u SPLIT\u FREE
将独立的
serialize()
函数拆分为
save()
load()
。对于侵入式序列化,它是
BOOST\u serialization\u SPLIT\u MEMBER

要编写通用的反序列化函数(例如,通过网络传输对象),可以使用模板:

template<typename T>
void transmit( const T& data ) {
    // ...
    archive << data
    socket << archive_stream;
}
您希望基于类未知的条件序列化
i
和/或
s
。您可以创建一个包装器来序列化它并添加状态,但如果对象位于向量(或其他类)内,则这将不起作用

让存档知道状态可能更容易:

#include <boost/archive/text_oarchive.hpp>

// using struct to omit a bunch of friend declarations    
struct oarchive : boost::archive::text_oarchive_impl<oarchive>
{
    oarchive(std::ostream& os, unsigned flags=0)
      : boost::archive::text_oarchive_impl<oarchive>(os,flags),mask(0){}

    // forward to base class
    template<class T> void save( T& t ) {
        boost::archive::text_oarchive_impl<oarchive>::save(t);
    }

    // this is the 'state' that can be set on the archive
    // and queried by the serialization functions
    unsigned get_mask() const { return mask; }
    void set_mask(unsigned m) { mask = m; }
    void clear_mask() { mask = 0; }
private:
    unsigned mask;
};

// explicit instantiation of class templates involved
namespace boost { namespace archive {
   template class basic_text_oarchive<oarchive>;
   template class text_oarchive_impl<oarchive>;
   template class detail::archive_serializer_map<oarchive>;
} }

// template implementations (should go to the .cpp)
#include <boost/archive/impl/basic_text_oarchive.ipp>
#include <boost/archive/impl/text_oarchive_impl.ipp>
#include <boost/archive/impl/archive_serializer_map.ipp>
以及设置状态的方法(这只是一个非常基本的示例):


oarchive&operator我确实想出了一个解决方案,虽然不太理想,但我觉得还是值得发布。基本上,我设置了一个singleton类来管理发送所有序列化请求,该类将跟踪用于该请求的最新位标志。因此,在序列化或反序列化期间,这些方法可以查询这些标志。这使我能够让Boost的
save
load
方法调用一组更健壮的方法,这些方法可以使用这些标志有选择地仅序列化某些成员

// Boost's `save` method, which must have this exact signature
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
    const unsigned int flags = SerializationManager::getFlags(); // SerializationManager is a singleton.
    saveData(ar, version, flags);
}

// Your own custom method, which can have whichever parameters you need
template<class Archive>
void saveData(Archive& ar, const unsigned int version, const unsigned int state_flags) const
{
    if (state_flags & INITIAL_SERIALIZATION)
    {
        // Serialize only data needed for an initial serialization
    }

    // Other serialization
}
//Boost的'save'方法,该方法必须具有此精确签名
模板
无效保存(存档和应收账款,常量未签名整数版本)常量
{
const unsigned int flags=SerializationManager::getFlags();//SerializationManager是一个单例。
保存数据(ar、版本、标志);
}
//您自己的自定义方法,可以有您需要的任何参数
模板
void saveData(存档和存档、常量无符号整数版本、常量无符号整数状态标志)常量
{
if(状态标志和初始序列化)
{
//仅序列化初始序列化所需的数据
}
//其他序列化
}
这里有一个更简单的方法:

// Boost's `save` method, which must have this exact signature
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
    const unsigned int flags = SerializationManager::getFlags(); //         SerializationManager is a singleton.
    ar << flags;
    if(flags && INITIAL_SERIALIZATION){
        // Serialize only data needed for an initial serialization
    }
    // Other serialization
}
template<class Archive>
void load(Archive& ar, const unsigned int version) const
{
    const unsigned int flags = SerializationManager::getFlags(); //         SerializationManager is a singleton.
    unsigned int flags;
    ar >> flags;
    if(flags && INITIAL_SERIALIZATION){
        // Serialize only data needed for an initial serialization
    }
    // Other serialization
}
//Boost的'save'方法,该方法必须具有此精确签名
模板
无效保存(存档和应收账款,常量未签名整数版本)常量
{
const unsigned int flags=SerializationManager::getFlags();//SerializationManager是一个单例。
ar>旗帜;
if(标志和初始\u序列化){
//仅序列化初始序列化所需的数据
}
//其他序列化
}

Boost的问题是我必须序列化一个类的成员,在某些情况下我想做的是只序列化一个类的部分,这些部分甚至可能不是成员变量,而是从成员变量的部分构造的数据。我不会完全连续的
struct Foo {
    Foo() : i(42), s("foo") {}
    int i;
    std::string s;
};
#include <boost/archive/text_oarchive.hpp>

// using struct to omit a bunch of friend declarations    
struct oarchive : boost::archive::text_oarchive_impl<oarchive>
{
    oarchive(std::ostream& os, unsigned flags=0)
      : boost::archive::text_oarchive_impl<oarchive>(os,flags),mask(0){}

    // forward to base class
    template<class T> void save( T& t ) {
        boost::archive::text_oarchive_impl<oarchive>::save(t);
    }

    // this is the 'state' that can be set on the archive
    // and queried by the serialization functions
    unsigned get_mask() const { return mask; }
    void set_mask(unsigned m) { mask = m; }
    void clear_mask() { mask = 0; }
private:
    unsigned mask;
};

// explicit instantiation of class templates involved
namespace boost { namespace archive {
   template class basic_text_oarchive<oarchive>;
   template class text_oarchive_impl<oarchive>;
   template class detail::archive_serializer_map<oarchive>;
} }

// template implementations (should go to the .cpp)
#include <boost/archive/impl/basic_text_oarchive.ipp>
#include <boost/archive/impl/text_oarchive_impl.ipp>
#include <boost/archive/impl/archive_serializer_map.ipp>
enum state { FULL=0x10, PARTIAL=0x20 };
oarchive& operator<<(oarchive& ar, state mask) {
    ar.set_mask(ar.get_mask()|mask);
    return ar;
}
namespace boost { namespace serialization {

template<class Archive>
void save(Archive & ar, const Foo& foo, const unsigned int version)
{
    int mask = ar.get_mask(); // get state from the archive
    ar << mask; // serialize the state! when deserializing,
    // read the state first and extract the data accordingly

    if( mask & FULL )
        ar << foo.s; // only serialize s if FULL is set
    ar << foo.i;     // otherwise serialize i only
    ar.clear_mask(); // reset the state
}

} } // boost::serialization

BOOST_SERIALIZATION_SPLIT_FREE(Foo)
int main() {
    std::stringstream strm;
    oarchive ar(strm);

    Foo f;
    ar << PARTIAL << f << FULL << f;

    std::cout << strm.str();
}
// Boost's `save` method, which must have this exact signature
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
    const unsigned int flags = SerializationManager::getFlags(); // SerializationManager is a singleton.
    saveData(ar, version, flags);
}

// Your own custom method, which can have whichever parameters you need
template<class Archive>
void saveData(Archive& ar, const unsigned int version, const unsigned int state_flags) const
{
    if (state_flags & INITIAL_SERIALIZATION)
    {
        // Serialize only data needed for an initial serialization
    }

    // Other serialization
}
// Boost's `save` method, which must have this exact signature
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
    const unsigned int flags = SerializationManager::getFlags(); //         SerializationManager is a singleton.
    ar << flags;
    if(flags && INITIAL_SERIALIZATION){
        // Serialize only data needed for an initial serialization
    }
    // Other serialization
}
template<class Archive>
void load(Archive& ar, const unsigned int version) const
{
    const unsigned int flags = SerializationManager::getFlags(); //         SerializationManager is a singleton.
    unsigned int flags;
    ar >> flags;
    if(flags && INITIAL_SERIALIZATION){
        // Serialize only data needed for an initial serialization
    }
    // Other serialization
}