2017-06-19 29 views
0

我有一个大的配置结构,它由子结构,int,char,long和字符串组成。子结构也是由相同的元素构建而成的。没有“保存”方法序列化一个大结构

此配置结构需要序列化并在群集上的节点之间发送。

我正在寻找一种序列化方式,而不需要在每个结构体中添加“保存”方法,如谷类和增强库所需。代码由少数程序员共享,结构非常大。恐怕有人会更新结构或其substructs的一个忘记更新“保存方法相应

想法?

**在CPP

+1

二进制表示是一个选项吗? –

+0

恐怕有人会更新结构或其子结构之一,并忘记更新“保存方法相应 - 这是测试的目的。如果你的配置可以与==很好地比较,那么你可以serialise,de -serialise,然后比较&断言相同 – UKMonkey

+0

@StephanLechner二进制表示是一个选项,我不在乎它是如何序列化的 – Epic

回答

0

如果你可以确定集群中的所有节点具有相同的体系结构并执行相同的编译代码,但实际上可以以二进制模式传输数据,即作为对象的“原始内存转储”。由于不同的体系结构和/或不同的编译器可能导致所使用的数据类型的不同大小以及不同的“填充”,因此需要相同的体系结构/相同的编译代码。然后,发送方和接收方使用的内存布局可能会不同,导致数据混乱。

请注意,您的“结构”(或类)必须是POD类型,即没有虚拟构造函数/析构函数,也没有虚拟成员函数,您可以使用“内存转储”初始化它。

如果您知道这些限制,请参阅以下代码,该代码通过以二进制模式写入和读取文件来“模拟”传输。调整此代码以使用您选择的频道实际传输代码,例如插座。

希望它有帮助。

struct myStruct { 
    int x; 
    int y; 
    char name[10]; 
    double z; 

    void printOnConsole() { 
     cout << "x:" << x << ";y:" << y << ";name:"<< name << ";z:" << z << endl; 
    } 
    void writeBinary(ofstream &out) { 
     out.write((char*)this, sizeof(*this)); 
    } 
    bool readBinary(ifstream &in) { 
     in.read((char*)this, sizeof(*this)); 
     return in.gcount() == sizeof(*this); 
    } 
}; 


int main() 
{ 
    myStruct myStructObjs[] = { 
     { 10, 20, "Herbert", 3.5 }, 
     { 30, 40, "Anton", 4.6 } 
    }; 
    cout << "Objects to be transferred:" << endl; 
    myStructObjs[0].printOnConsole(); 
    myStructObjs[1].printOnConsole(); 

    cout << "Simulating transfer:" << endl; 
    ofstream send("data.bin", ios_base::binary | ios_base::out); 
    if (send) { 
     myStructObjs[0].writeBinary(send); 
     myStructObjs[1].writeBinary(send); 
     send.close(); 
     cout << "Two objects transferred." << endl; 
    } 
    else { 
     cout << "Error 'sending' data." << endl; 
     return 1; 
    } 


    cout << "Simulating receive:" << endl; 
    ifstream receive("data.bin", ios_base::binary); 
    if (receive) { 
     myStruct receivedObj; 
     int n = 0; 
     while (receivedObj.readBinary(receive)) { 
      receivedObj.printOnConsole(); 
      n++; 
     } 
     cout << n << " objects received." << endl; 
    } 
    else { 
     cout << "Error 'receiving' data." << endl; 
     return 1; 
    } 

    return 0; 
} 
+0

我的结构不是POD,因为它具有字符串,但是在阅读完它后,最好使它们成为char []并按照你的建议进行操作。我应该为其他人注意,如果他们使用cpp 14,他们可以使用boost hana来遍历结构并轻松地序列化 – Epic

0

加速提供了一个非侵入性的方式来序列,see here下的“非侵入式版本”

+0

鉴于OP已经声明他们意识到boost,我不认为这个答案 – UKMonkey

+0

他的问题意味着他认为他必须使用boost来将保存方法放入课程中,而非非侵入式版本的情况并非如此 – mattideluxe

+0

@mattideluxe问题并非天气将保存在内部。问题是开发人员可能会意外忘记在两个地方都输入新的值 – Epic

0

有一个在C++,QT和虚幻引擎没有任何反映正用自己的编译步骤来创建用于这一目的的代码反思。您也可以看看cpp3k这是一个铿锵扩展。

我可以建议你一个方法,以确保结构改造而适当更新的保存功能是明显的:

struct myData { 
int32_t a; 
uint8_t b; 
}; 

void save(const myData& data) { 
    save(data.a); 
    save(data.b); 
    assert(sizeof(myData) == 5); // When adding new elements to myData make sure to update this function 
} 

附:确保对齐不会影响您的尺寸。


UPD。

此图书馆可能会帮助您在magic_get。 同样这两篇文章都非常有趣An Introduction to Reflection in C++Fun with Reflection in C++

UPD.2

你可能想看看protocol buffers或类似的库。

+0

tnx,我会阅读他们 – Epic

+0

我遇到了在你的链接增加hana。这似乎允许遍历结构成员。我不能使用它,因为它需要cpp 14,但它可能对某人有用 – Epic

0

恐怕有人会更新结构或其substructs的一个忘记更新“保存方法相应

怎么样把一个

McCfgStruct::serialize(...) { 
    std::static_assert(sizeof(MyCfgStruct) == 32); 
} 

(或同等学历)这方式,如果有人在结构中添加一个新变量,并且不更新序列化方法的预期大小,您将得到编译器错误。

相关问题