Я бы не стал давать полноценный ответ, поскольку у меня нет под рукой MCVE. Однако ОП запросил дополнительные разъяснения и относительно CopyMemory()
Я нашел некоторые вещи, которые стоит отметить (и это было слишком долго, чтобы писать комментарий только об этом).
CopyMemory()
ничто особенно посвящен файлам с отображением памяти. Это просто функция для копирования данных в место назначения из источника с размером в байтах.
При поиске в Google CopyMemory()
я наткнулся на "CopyMemory()
против memcpy()
" и нашел краткий ответ на Разработчик игр:
Прямо из 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()
возвращает указатель на память, в которую был отображен файл. Доступ для чтения/записи может быть выполнен впоследствии, как и любой другой доступ к памяти процесса через оператор присваивания, через memcpy()
(или CopyMemory()
) или что-либо еще, что только можно себе представить.
Наконец, ответ на дополнительный вопрос ОП:
как я мог прочитать данные в массив строк/байтов на «другой» стороне, где я читал из общей памяти?
Чтение может быть выполнено точно таким же образом, за исключением того, что указатель на представление карты становится источником, а локальный буфер становится местом назначения. Но как определить размер? Этот вопрос на самом деле более общий: сколько байтов занимают данные переменной длины? В C/C++ есть два типичных ответа:
- либо сохранить размер данных (например,
std::string
, std::vector
и т. д.)
- или как-то отметить конец данных (например, нулевой терминатор в строках C).
В конкретном случае ОП первый вариант, вероятно, более разумен. Таким образом, размер данных полезной нагрузки (изображение) также может храниться в файле отображения памяти. На стороне считывателя сначала оценивается размер (который должен иметь определенный тип 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[]()
имел неконстантную версию.
person
Scheff's Cat
schedule
09.05.2018
std::string
, вы злоупотребилиchar
представлением байтов. Это нормально, и я бы поступил так же. Пример с общей памятью MSDN имеет дело с текстовыми строками, которые могут использовать расширенные символы в зависимости от того, как определеноTCHAR
. Забудьте об этом - в вашем случае это не имеет значения.CopyMemory((PVOID)pBuf, data.data(), data.size());
должно быть хорошо. - person Scheff's Cat   schedule 06.05.2018boost.interprocess
, а не Win32 API. - person Asesh   schedule 06.05.2018