Я бы не стал давать полноценный ответ, так как у меня нет MCVE под рукой. Тем не менее, ОП попросил дать дополнительные разъяснения, и относительно CopyMemory()
я нашел некоторые вещи, на которые стоит обратить внимание (и было слишком долго писать комментарий только об этом).
CopyMemory()
не имеет ничего общего с файлами, отображаемыми в память. Это просто функция для копирования данных в пункт назначения из источника с размером в байтах.
Пока гуглял для CopyMemory()
, я наткнулся на "CopyMemory()
против memcpy()
" и нашел такой же хороший и короткий ответ на GameDev :
Прямо из WINBASE.H
#define CopyMemory RtlCopyMemory
Тогда прямо из WINNT.H
#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length))
Итак, вот и мы:
std::memcpy()
Определено в заголовке <cstring>
void* memcpy( void* dest, const void* src, std::size_t count );
Копирует count
байтов с объекта, на который указывает src
, на объект, на который указывает dest
. Оба объекта интерпретируются как массивы unsigned char
.
Если объекты перекрываются, поведение не определено.
Для особого случая (потенциально) перекрывающихся диапазонов источника / назначения, memcpy()
имеет «родного брата» memmove()
. В этом случае файлы с отображением в памяти, я не верю, что источник и назначение могут когда-либо пересекаться. Таким образом, memcpy()
может быть в порядке (и, возможно, даже быстрее, чем memmove()
.)
Итак, это не CopyMemory()
, который обеспечивает «Магию доступа к файлу с отображением в памяти». Это уже произошло в другом вызове функции, который обязательно находится в исходном коде OP, но не упоминается в вопросе:
MapViewOfFile()
Сопоставляет представление файла с адресным пространством вызывающего процесса.
Возвращаемое значение
Если функция завершается успешно, возвращаемое значение является начальным адресом отображенного представления.
Следовательно, в случае успеха MapViewOfFile()
возвращает указатель на память, в которую был отображен файл. Доступ на чтение / запись может быть выполнен впоследствии, как и любой другой доступ к памяти процесса & ndash; через оператора присваивания, через memcpy()
(или CopyMemory()
) или что-либо еще мыслимое.
Наконец, ответ на дополнительный вопрос OP:
как я могу прочитать данные в строку / байтовый массив на "другой" стороне, где я читаю из общей памяти?
Чтение может быть выполнено точно таким же образом, за исключением того, что указатель на представление карты становится источником, а локальный буфер становится местом назначения. Но как определить размер? Эта проблема на самом деле более общая: сколько байтов занимают данные с переменной длиной? В C / C ++ есть два типичных ответа:
- также храните размер данных (как в
std::string
, std::vector
и т. Д.)
- или как-то отметить конец данных (например, нулевой терминатор в строках C).
В конкретном случае OP первый вариант, вероятно, более целесообразен. Таким образом, размер данных полезной нагрузки (изображения) также может быть сохранен в файле отображения памяти. На стороне читателя сначала оценивается размер (который должен иметь определенный тип int
и, следовательно, известное количество байтов), а размер используется для копирования данных полезной нагрузки.
Следовательно, на стороне писателя это может выглядеть так:
/* prior something like
* unsigned char *pBuf = MapViewOfFile(...);
* has been done.
*/
// write size:
size_t size = data.size();
CopyMemory(pBuf, (const void*)&size, sizeof size);
// write pay-load from std::string data:
CopyMemory(pBuf + sizeof size, data.data(), size);
На стороне читателя это может выглядеть так:
/* prior something like
* const unsigned char *pBuf = MapViewOfFile(...);
* has been done.
*/
// read size:
size_t size = 0;
CopyMemory((void*)&size, pBuf, sizeof size);
// In C, I had probably done: size_t size = *(size_t*)pBuf; instead...
// allocate local buffer for pay-load
std::string data(size, '\0');
// read pay-load
CopyMemory(&data[0], pBuf + sizeof size, size);
Обратите внимание, что &data[0]
предоставляет тот же адрес, что и data.data()
. До C ++ 17 не существует неконстантной версии std::string::data()
, следовательно, взломать std::string::operator[]()
с неконстантной версией.