【问题标题】:C++, ECS and Saving / LoadingC++、ECS 和保存/加载
【发布时间】:2015-03-18 17:44:20
【问题描述】:

我有一个使用实体-组件-系统框架的程序。本质上,这意味着我有一个实体集合,这些实体附加了各种组件。实体实际上只是整数 ID 号,通过将组件映射到实体的指定 ID 号来附加组件。

现在,我需要将实体集合和相关组件存储到一个可以稍后修改的文件中,所以基本上我需要一个保存和加载功能。但是,作为 C++ 的新手,我很难弄清楚如何准确地做到这一点。

来自 Java 和 C#,我的第一选择是将对象序列化为 JSON,然后在加载 JSON 时反序列化它们。但是,C++ 没有任何反射特性。所以,问题是:如何保存和加载 C++ 对象?我不是指实际的文件操作,我指的是为了在程序启动之间保留它们而应处理的对象和结构的方式。

【问题讨论】:

  • 只要稍微看一下,就有很多序列化库。因为,正如您所指出的,C++ 没有反射,所以没有您的帮助,任何库都无法工作,通常以您编写对每个可序列化结构的数据进行实际序列化/反序列化的函数的形式(例如,让您将成员写入流就像写入 std::cout)。
  • @JoachimPileborg 我在搜索时确实找到了一些库。但问题是,我不知道如何根据序列化数据构造正确的对象。假设有一个组件 FooComponent 和另一个名为 BarComponent 的组件 - 如果没有反射数据,我怎么知道要构造哪个组件?
  • 这取决于您使用的库。有些允许您将工厂函数与标识符一起注册,序列化器会将标识符放入流中以供反序列化器读取,以便它可以调用正确的工厂函数。其他库自己处理它,这意味着您必须自己跟踪它(可能通过标识符工厂函数映射)。

标签: c++ serialization entity components deserialization


【解决方案1】:

一种方法是在 C++ 中创建Persistent Objects,并存储您的数据。

查看以下链接:

类似永恒的C++对象持久化库

http://sourceforge.net/projects/litesql/

http://en.wikipedia.org/wiki/ODB_(C%2B%2B)

http://drdobbs.com/cpp/184408893

http://tools.devshed.com/c/a/Web-Development/C-Programming-Persistence/

C++ 不直接支持持久性(未来有人提议在 C++ 中添加持久性和反射)。持久性支持并不像起初看起来那么微不足道。同一对象的大小和内存布局可能因平台而异。不同的字节顺序或字节序使事情变得更加复杂。为了使对象持久化,我们必须将其状态保留在非易失性存储设备中。即:编写一个持久对象以在创建它的程序范围之外保留其状态。

另一种方式,是将对象存储到数组中,然后将数组缓冲区推送到文件中。 优点是磁盘盘片不会浪费时间加速,并且可以连续执行写入。

您可以通过使用线程来提高性能。将对象转储到缓冲区,完成后触发线程处理输出。

示例: 以下代码未经编译,仅供说明之用。

#include <fstream>
#include <algorithm>

using std::ofstream;
using std::fill;

#define MAX_DATA_LEN  1024 // Assuming max size of data be 1024

class stream_interface
{
    virtual void    load_from_buffer(const unsigned char *& buf_ptr) = 0;
    virtual size_t  size_on_stream(void) const = 0;
    virtual void    store_to_buffer(unsigned char *& buf_ptr) const = 0;
};

struct Component 
    : public stream_interface,
    data_length(MAX_DATA_LEN)
{
    unsigned int entity;
    std::string  data;
    const unsigned int  data_length;

    void load_from_buffer(const unsigned char *& buf_ptr)
    {
        entity = *((unsigned int *) buf_ptr);
        buf_ptr += sizeof(unsigned int);
        data = std::string((char *) buf_ptr);
        buf_ptr += data_length;
        return;
    }
    size_t size_on_stream(void) const
    {
        return sizeof(unsigned int) + data_length;
    }
    void store_to_buffer(unsigned char *& buf_ptr) const
    {
        *((unsigned int *) buf_ptr) = entity;
        buf_ptr += sizeof(unsigned int);
        std::fill(buf_ptr, 0, data_length);
        strncpy((char *) buf_ptr, data.c_str(), data_length);
        buf_ptr += data_length;
        return;
    }
};


int main(void)
{
    Component c1;
    c1.data = "Some Data";
    c1.entity = 5;
    ofstream    data_file("ComponentList.bin", std::ios::binary);

    // Determine size of buffer
    size_t  buffer_size = c1.size_on_stream();

    // Allocate the buffer
    unsigned char * buffer = new unsigned char [buffer_size];
    unsigned char * buf_ptr = buffer;

    // Write / store the object into the buffer.
    c1.store_to_buffer(buf_ptr);

    // Write the buffer to the file / stream.
    data_file.write((char *) buffer, buffer_size);

    data_file.close();
    delete [] buffer;
    return 0;
}

【讨论】:

    猜你喜欢
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    相关资源
    最近更新 更多