C ++ Boost :: serialization:如何在一个程序中归档一个对象并在另一个程序中恢复它?

时间:2014-11-22 04:07:09

标签: c++ serialization boost

我正在使用Boost Serialization来保存和加载游戏的整体状态,以及在外部存储地图和生物数据。

我有两个程序。第一个运行游戏本身,根据外部文件中保存的数据创建必要的新对象。它还生成自己状态的保存文件。到目前为止,这些都有效。

第二,我正在创建一个专门的编辑器。我想用它来创建和操作游戏程序使用的所述文件。

所以我在所有需要外部文件的类的第二个程序中制作镜像,但是为了编辑的目的,它们具有不同的功能。

中的所有数据
void serialize(AreaArchive & aar, const unsigned int version)
{...}

任一程序类的一部分都是相同的。

我用它来创建文件:

areaGen.push_back(new Area("area1"));

std::string fileName;

for(std::vector<Area*>::iterator it = areaGen.begin(); it != areaGen.end(); ++it)
{
    fileName = (*it)->name + ".areabase";
    std::ofstream areafile(fileName);

    boost::archive::text_oarchive outArchive(areafile);
    outArchive << *it;
}

该文件,假设“area1.areabase”完美生成AFAIK。我将它移动到我的第一个程序的目录,执行函数

bool LoadAreaState(std::string areaName, Area *target, bool baseState)
{
std::cout << "Debug: entered area loading function..." << std::endl;

std::string fileName;
if(baseState)
    fileName = areaName + ".areabase";
else
    fileName = areaName + ".areafile";

std::ifstream areafile(fileName);

...

std::cout << "Debug: file opened sucessfully..." << std::endl;

boost::archive::text_iarchive inArchive(areafile);

std::cout << "Debug: inarchive to target..." << std::endl;

inArchive >> *target; // The step at which it fails - Terminate by boost::serialization's exception

std::cout << "Debug: target Area object restored..." << std::endl;

return true;
}

当然它不起作用。无论如何,第一个和第二个程序中类的成员对象不能相同。可以吗?但序列化块包含完全相同的类型数据。

我希望这个例子能够表达我想要做的事情。但有没有办法让它发挥作用?

非常感谢。

2 个答案:

答案 0 :(得分:1)

通常,Boost序列化不支持这种行为。

对于严格的琐碎(POD,当然不是虚拟类型),你将能够侥幸逃脱。例如。我过去已将map<K,V>序列化,并将其反序列为flat_map<K,V>),用于琐碎的KV。但是,这些都不适用于库,您应该考虑未指定的行为。因此,除非您已经为自己验证了alll代码路径,以确保您正在做的事情将起作用,以及为什么,不要使用Boost序列化来实现智能。

现在,这是一个应该工作的简单示例:

 struct A { 
     int x;
     virtual void display() const; {}
 };

 struct B {
     int x
     virtual void display() const; {}
 };

类型将不相关,将从Boost序列化中检查RTTI。

如何解决这个问题?

你可以

  • 将可序列化类型移动到共享(静态)库中,并使用两个程序中完全相同的代码。问题消失了,因为类型信息是共享的
  • 使用自定义二进制序列化
  • 使用共享内存/内存映射文件(虽然这不是微不足道的,所以只有当您确信自己可以执行上述操作时才这样做)。

重要 Boost序列化二进制存档,实际上非常便携!您应该查看[EOS Portable Archives](通常,Boost序列化不支持此行为。

对于严格的琐碎(POD,当然不是虚拟类型),你将能够侥幸逃脱。例如。我过去已将map<K,V>序列化并将其反序列化为flat_map<K,V>)。但是,这些都不适用于库,您应该考虑未指定的行为。因此,除非您已经为自己验证了alll代码路径,以确保您正在做的事情将起作用,以及为什么,不要使用Boost序列化来实现智能。

现在,这是一个应该工作的简单示例:

 struct A { 
     int x;
     virtual void display() const; {}
 };

 struct B {
     int x
     virtual void display() const; {}
 };

类型将不相关,将从Boost序列化中检查RTTI。

如何解决这个问题?

你可以

  • 将可序列化类型移动到共享(静态)库中,并使用两个程序中完全相同的代码。问题消失了,因为类型信息是共享的
  • 使用自定义二进制序列化
  • 使用共享内存/内存映射文件(虽然这不是微不足道的,所以只有当您确信自己可以执行上述操作时才这样做)。

重要 Boost序列化二进制存档,实际上非常便携!如果要在不同的计算机上共享存档,则应查看EOS Portable Archives。 )如果你想在不同的机器上共享档案等。

答案 1 :(得分:-1)

关于如何从异常中打印消息的一个非常简单的示例:

try
{
    inArchive >> *target;
}
catch (std::exception& e)
{
    std::cerr << "Exception: " << e.what() << '\n';
}