2015-01-20 2 views
1

У меня есть программа, которая использует инфраструктуру системы сущностей. По сути, это означает, что у меня есть набор объектов, к которым прикреплены различные компоненты. Объекты на самом деле являются целыми идентификационными номерами, а к ним привязаны компоненты, сопоставляя компонент с указанным идентификационным номером объекта.C++, ECS и сохранение/загрузка

Теперь мне нужно сохранить коллекции объектов и связанных компонентов в файл, который может быть изменен позже, поэтому в основном мне нужны функции сохранения и загрузки. Однако, будучи новичком на C++, мне трудно понять, как это сделать.

Исходя из Java и C#, моим первым выбором было бы сериализовать объекты, скажем, в JSON, а затем десериализовать их при загрузке JSON. Однако C++ не имеет никаких функций отражения. Итак, возникает вопрос: как мне сохранить и загрузить объекты C++? Я не имею в виду фактические операции с файлами, я имею в виду способ, которым должны обрабатываться объекты и структуры, чтобы сохранить их между запусками программ.

+0

Существует много библиотек сериализации, если вы просто немного выглядите. Поскольку, как вы отметили, C++ не имеет отражения, ни одна из библиотек не работает без вашей помощи, часто в форме написания функции, которая выполняет фактическую сериализацию/десериализацию данных каждой сериализуемой структуры (например, пуская вы пишете элементы в поток, точно так же, как написание, например, 'std :: cout'). –

+0

@JoachimPileborg Я нашел некоторые библиотеки, когда искал. Дело в том, что я не знаю, как построить правильный объект на основе сериализованных данных. Предположим, что есть компонент 'FooComponent' и еще один, называемый' BarComponent' - как узнать, какой из них построить без данных отражения? – manabreak

+0

Это зависит от используемой библиотеки. Некоторые позволяют вам регистрировать заводские функции вместе с идентификатором, а сериализатор помещает идентификатор в поток для чтения десериализатора, чтобы он мог вызывать правильную заводскую функцию. Другие библиотеки обрабатывают его самостоятельно, а это значит, что вы должны сами отслеживать это (возможно, через сопоставление идентификаторов и фабричных функций). –

ответ

1

Один из способов сделать это - создать Persistent Objects на C++ и сохранить ваши данные.

проверить следующие ссылки:

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; 
}