2012-08-10 51 views
0

我有結構和載體,看起來像:CopyMemory的非POD

typedef struct 
{ 
    int SX, SY; 
    int X, Y, Z; 
    std::vector<Vector3D> Vertices; 
    const void* VBOPointer; 
} Model; 

typedef struct 
{ 
    int X, Y; 
    struct 
    { 
     int VX[4], VY[4]; 
     int TX[4], VY[4]; 
    } Quad; 
} Item; 

std::vector<Item> ListOfItems; 
std::vector<Model> ListOfModels; 

我需要將這些數據複製到內存,所以我可以從其他程序重建他們。我已經映射了內存,但後來我意識到我無法在其中任何一個上使用CopyMemory或MemCpy。

我該如何複製它?

我如何複製標準數據類型/結構

例子:

struct 
{ 
    int X; 
    int Y; 
} POD; 

//pData is a void pointer to mapped memory given to be by MapFileView.. 

POD Foo = {100, 50}; 
long double* Data = static_cast<long double*>(pData); 
//Check if Data[1] contains a request command then copy. 

CopyMemory(&Data[0], &Foo, sizeof(Foo)); 
+1

我會寫一個序列化和反序列化功能,爲每個類 – Gir 2012-08-10 21:10:21

+0

使用第三方 - 谷歌的protobuf想到的。 – 2012-08-10 21:11:25

+0

XDR是完全獨立於相關機器的標準方式。你可以像@Gir所說的那樣在你的'Serialize'和'Deserialize'函數中使用它。 – Hbcdev 2012-08-10 21:15:45

回答

2

既然你要處理非POD數據,您需要將結構數據壓扁成一個序列化格式,其他應用程序可以再在其結尾解析回結構。

你的ListOfItems矢量可以非常容易扁平,因爲它的元素是POD數據。存儲vector大小的整數,複製到緩衝區,然後複製每個Item事後(假設緩衝器是足夠大以保持扁平的數據):

long double* Data = static_cast<long double*>(pData); 
//Check if Data[1] contains a request command then copy. 

unsigned char *Work = static_cast<unsigned char *>(pData); 

int number = ListOfItems.size(); 
CopyMemory(Work, &number, sizeof(int)); 
Work += sizeof(int); 

for (int i = 0; i < number; ++i) 
{ 
    CopyMemory(Work, &ListOfItems[i], sizeof(Item)); 
    Work += sizeof(Item); 
} 

ListOfModels矢量將是有點困難變平因爲Model包含另一個vector中,但相同的概念適用於一般:

long double* Data = static_cast<long double*>(pData); 
//Check if Data[1] contains a request command then copy. 

unsigned char *Work = static_cast<unsigned char *>(pData); 

int number = ListOfModels.size(); 
CopyMemory(Work, &number, sizeof(int)); 
Work += sizeof(int); 

for (int i = 0; i < number; ++i) 
{ 
    Model &m = ListOfModels[i]; 

    CopyMemory(Work, &(m.SX), sizeof(int) * 5); 
    Work += (sizeof(int) * 5); 

    int num = m.Vertices.size(); 
    CopyMemory(Work, &num, sizeof(int)); 
    Work += sizeof(int); 

    for (int j = 0; j < num; ++j) 
    { 
     Vector3D &v = m.Vertices[j]; 
     // copy v as needed... 
     Work += ...; 
    } 

    // copy m.VBOPointer as needed ... 
    Work += ...; 
} 

我通常這樣的事情做的是使用模板來幫助簡化邏輯,使其更易於閱讀:

template<typename T> 
void Copy(unsignd char* &Work, const T &value) 
{ 
    CopyMemory(Work, &value, sizeof(T)); 
} 

template<template T> 
void Copy(unsigned char* &Work, const std::vector<T> &vec) 
{ 
    int number = vec.size(); 
    Copy(Work, number); 
    for (int i = 0; i < number; ++i) 
     Copy(Work, vec[i]); 
} 

long double* Data = static_cast<long double*>(pData); 
//Check if Data[1] contains a request command then copy. 

unsigned char *Work = static_cast<unsigned char *>(pData); 
Copy(Work, ListOfItems); 

template<> 
void Copy<Vector3D>(unsigned char* &Work, const Vector3D &vec) 
{ 
    // copy vec as needed... 
    Work += ...; 
} 

template<> 
void Copy<Model>(unsigned char* &Work, const Model &m) 
{ 
    Copy(Work, m.SX); 
    Copy(Work, m.SY); 
    Copy(Work, m.X); 
    Copy(Work, m.Y); 
    Copy(Work, m.Z); 
    Copy(Work, m.Vertices); 

    // copy m.VBOPointer as needed ... 
    Work += ...; 
} 

long double* Data = static_cast<long double*>(pData); 
//Check if Data[1] contains a request command then copy. 

unsigned char *Work = static_cast<unsigned char *>(pData); 
Copy(Work, ListOfModels); 
+0

'size_t'比'int'(或者至少是'unsigned')更合適。 – GManNickG 2012-08-10 21:57:09

+0

當然,'size_t'適合匹配'size()'(甚至更好,'std :: vector :: size_type')。但出於序列化的目的,最好選擇一種類型,這兩種應用程序都可以識別並可以就字節大小,字節序等等達成一致。所以我可能會更願意使用'uint32_t'來處理字節大小,並且只要應用程序在同一臺機器上,那麼endian不是問題,但如果應用程序在不同的機器上彼此通信(序列化獲得了該能力),則確實會成爲問題。 – 2012-08-10 22:32:07