gpt4 book ai didi

C++ WINAPI 共享内存动态数组

转载 作者:行者123 更新时间:2023-11-28 05:36:42 25 4
gpt4 key购买 nike

我正在尝试使用共享内存共享包含 2 个动态数组的结构数组,以便在另一个进程中使用这些结构。到目前为止,我可以共享一个结构数组,但它们还不包含动态数组。对完成此问题的任何帮助都会很棒。

预期:

typedef struct {
int id;
int type;
int count;
int[] values;
int[] settings;
} Entry;

当前代码:

typedef struct {
int id;
int type;
int count;
} Entry;

BOOL DumpEntries(TCHAR* memName) {
int size = entries.size() * sizeof(Entry) + sizeof(DWORD);

::hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, memName);
if (::hMapObject == NULL) {
return FALSE;
}

::vMapData = MapViewOfFile(::hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, size);
if (::vMapData == NULL) {
CloseHandle(::hMapObject);
return FALSE;
}

(*(DWORD*)::vMapData) = entries.size();
Entry* eArray = (Entry*)(((DWORD*)::vMapData) + 1);
for(int i = entries.size() - 1; i >= 0; i--) eArray[i] = entries.at(i);

UnmapViewOfFile(::vMapData);
return TRUE;
}

BOOL ReadEntries(TCHAR* memName, Entry** entries, DWORD &number_of_entries) {
HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, memName);
if (hMapFile == NULL) {
return FALSE;
}

DWORD *num_entries = (DWORD*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (num_entries == NULL) {
CloseHandle(hMapFile);
return FALSE;
}
number_of_entries = *num_entries;

if(number_of_entries == 0)
{
// special case: when no entries was found in buffer
*entries = NULL;
return true;
}

Entry* tmpEntries = (Entry*)(num_entries + 1);

*entries = new Entry[*num_entries];

for (UINT i = 0; i < *num_entries; i++) {
(*entries)[i] = tmpEntries[i];
}

UnmapViewOfFile(num_entries);
CloseHandle(hMapFile);

return TRUE;
}

最佳答案

您不能跨进程边界传递指针,因此您不能将指针存储在您放入共享内存的 struct 项中。您可以做的是分配共享内存块本身足够大以容纳所有数组数据,然后根据需要使用偏移量访问各种数组,例如:

typedef struct
{
int id;
int type;
int count;
int *values;
int *settings;
} Entry;

#pragma pack(push, 1)
typedef struct
{
int id;
int type;
int count;
DWORD values_offset;
DWORD values_count; // if different than 'int count'
DWORD settings_offset;
DWORD settings_count; // if different than 'int count'
} SharedMemEntry;
#pragma pack(pop)

BOOL DumpEntries(TCHAR* memName)
{
DWORD NumValues = 0;
DWORD NumSettings = 0;

// or whatever your container actually is...
for(std::vector<Entry>::reverse_iterator iter = entries.rbegin();
iter != entries.rend(); ++iter)
{
Entry &e = *iter;

// or whatever you have to do to calculate how many
// integers are in the values[] and settings[] arrays...
//
NumValues += e.count;
NumSettings += e.count;
}

DWORD memsize = sizeof(DWORD) +
(entries.size() * sizeof(SharedMemEntry)) +
(sizeof(int) * NumValues) +
(sizeof(int) * NumSettings);

if (hMapObject != NULL)
CloseHandle(hMapObject);

hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, memsize, memName);
if (hMapObject == NULL) {
return FALSE;
}

BYTE *vMapData = (BYTE*) MapViewOfFile(hMapObject, FILE_MAP_WRITE, 0, 0, memsize);
if (vMapData == NULL) {
CloseHandle(hMapObject);
hMapObject = NULL;
return FALSE;
}

DWORD *pEntryCount = (DWORD*) vMapData;
*pEntryCount = entries.size();

SharedMemEntry* pEntries = (SharedMemEntry*) (pEntryCount + 1);
int *pValues = (int*) (pEntries + entries.size());
int *pSettings = (int*) (pValues + NumValues);

// or whatever your container actually is...
for(std::vector<Entry>::reverse_iterator iter = entries.rbegin();
iter != entries.rend(); ++iter)
{
Entry &e = *iter;
SharedMemEntry &eEntry = *pEntries++;

eEntry.id = e.id;
eEntry.type = e.type;
eEntry.count = e.count;

eEntry.values_offset = ((BYTE*)pValues - vMapData);
eEntry.values_count = e.count; // or whatever you need...
for(DWORD k = 0; k < eEntry.values_count; ++k) {
*pValues++ = e.values[k];
}

eEntry.settings_offset = ((BYTE*)pSettings - vMapData);
eEntry.settings_count = e.count; // or whatever you need...
for(DWORD k = 0; k < eEntry.settings_count; ++k) {
*pSettings++ = e.settings[k];
}
}

UnmapViewOfFile(vMapData);
return TRUE;
}

BOOL ReadEntries(TCHAR* memName, Entry** entries, DWORD &num_entries)
{
HANDLE hMapFile = OpenFileMapping(FILE_MAP_READ, FALSE, memName);
if (hMapFile == NULL) {
return FALSE;
}

BYTE *vMapData = (BYTE*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (vMapData == NULL) {
CloseHandle(hMapFile);
return FALSE;
}

DWORD *pEntryCount = (DWORD*) vMapData;
num_entries = *pEntryCount;

if (num_entries == 0)
{
// special case: when no entries was found in buffer
*entries = NULL;
}
else
{
SharedMemEntry *pEntries = (SharedMemEntry*) (pEntryCount + 1);

*entries = new Entry[num_entries];

for (DWORD i = 0; i < num_entries; ++i)
{
Entry &e = (*entries)[i];
SharedMemEntry &eEntry = pEntries[i];

e.id = eEntry.id;
e.type = eEntry.type;
e.count = eEntry.count;

e.values = new int[eEntry.values_count];
e.settings = new int[eEntry.settings_count];

int *pValues = (int*) (vMapData + eEntry.values_offset);
for(DWORD j = 0; j < eEntry.values_count; ++j) {
e.values[j] = pValues[j];
}

int *pSettings = (int*) (vMapData + eEntry.settings_offset);
for(DWORD j = 0; j < eEntry.settings_count; ++j) {
e.settings[j] = pSettings[j];
}
}
}

UnmapViewOfFile(vMapData);
CloseHandle(hMapFile);

return TRUE;
}

或者,您应该考虑自动化内存管理和循环,而不是手动执行所有操作:

typedef struct
{
int id;
int type;
int count;
std::vector<int> values;
std::vector<int> settings;
} Entry;

#pragma pack(push, 1)
typedef struct
{
int id;
int type;
int count;
DWORD values_offset;
DWORD values_count; // if different than 'int count'
DWORD settings_offset;
DWORD settings_count; // if different than 'int count'
} SharedMemEntry;
#pragma pack(pop)

BOOL DumpEntries(TCHAR* memName)
{
DWORD NumValues = 0;
DWORD NumSettings = 0;

// or whatever your container actually is...
for(std::vector<Entry>::reverse_iterator iter = entries.rbegin();
iter != entries.rend(); ++iter)
{
Entry &e = *iter;
NumValues += e.values.size();
NumSettings += e.settings.size();
}

DWORD memsize = sizeof(DWORD) +
(entries.size() * sizeof(SharedMemEntry)) +
(sizeof(int) * NumValues) +
(sizeof(int) * NumSettings);

if (hMapObject != NULL)
CloseHandle(hMapObject);

hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, memsize, memName);
if (!hMapObject) {
return FALSE;
}

std::unique_ptr<void, decltype(&UnmapViewOfFile)> uMapData( MapViewOfFile(hMapObject, FILE_MAP_WRITE, 0, 0, memsize), &UnmapViewOfFile );
BYTE *vMapData = (BYTE*) uMapData.get();
if (!vMapData) {
CloseHandle(hMapObject);
hMapObject = NULL;
return FALSE;
}

DWORD *pEntryCount = (DWORD*) vMapData;
*pEntryCount = entries.size();

SharedMemEntry* pEntries = (SharedMemEntry*) (pEntryCount + 1);
int *pValues = (int*) (pEntries + entries.size());
int *pSettings = (int*) (pValues + NumValues);

// or whatever your container actually is...
for(std::vector<Entry>::reverse_iterator iter = entries.rbegin();
iter != entries.rend(); ++iter)
{
Entry &e = *iter;
SharedMemEntry &eEntry = *pEntries++;

eEntry.id = e.id;
eEntry.type = e.type;
eEntry.count = e.count;

eEntry.values_offset = ((BYTE*)pValues - vMapData);
eEntry.values_count = e.values.size();
pValues = std::copy(e.values.begin(), e.values.end(), pValues);

eEntry.settings_offset = ((BYTE*)pSettings - vMapData);
eEntry.settings_count = e.settings.size();
pSettings = std::copy(e.settings.begin(), e.settings.end(), pSettings);
}

return TRUE;
}

// or whatever container type you want...
BOOL ReadEntries(TCHAR* memName, std::vector<Entry> &entries)
{
entries.clear();

std::unique_ptr<std::remove_pointer<HANDLE>::type, decltype(&CloseHandle)> uMapFile( OpenFileMapping(FILE_MAP_READ, FALSE, memName), &CloseHandle );
HANDLE hMapFile = uMapFile.get();
if (!hMapFile) {
return FALSE;
}

std::unique_ptr<void, decltype(&UnmapViewOfFile)> uMapData( MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0), &UnmapViewOfFile );
BYTE *vMapData = (BYTE*) uMapData.get();
if (!vMapData) {
return FALSE;
}

DWORD *pEntryCount = (DWORD*) vMapData;
DWORD num_entries = *pEntryCount;

if (num_entries != 0)
{
entries.resize(num_entries);

SharedMemEntry *pEntries = (SharedMemEntry*) (pEntryCount + 1);

for (DWORD i = 0; i < num_entries; ++i)
{
Entry &e = entries[i];
SharedMemEntry &eEntry = pEntries[i];

e.id = eEntry.id;
e.type = eEntry.type;
e.count = eEntry.count;

e.values.reserve(eEntry.values_count);
e.settings.reserve(eEntry.settings_count);

int *pValues = (int*) (vMapData + eEntry.values_offset);
std::copy(pValues, pValues + eEntry.values_count, std::back_inserter(e.values));

int *pSettings = (int*) (vMapData + eEntry.settings_offset);
std::copy(pSettings, pSettings + eEntry.settings_count, std::back_inserter(e.settings));
}
}

return TRUE;
}

无论哪种方式,请确保您在 DumpEntries()ReadEntries() 之间提供某种同步,例如来自 CreateEvent()< 的共享事件,以便 ReadEntries() 不会在 DumpEntries() 仍在写入内存时尝试从内存中读取,反之亦然。

关于C++ WINAPI 共享内存动态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38128514/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com