我不会提供完整的答案,因为我手头没有MCVE。但是,OP 要求进行更多澄清,并且关于CopyMemory()
我发现一些值得注意的事情(仅对此发表评论有点太长了)。
CopyMemory()
没有什么特别专用于内存映射文件。它只是一个将数据从源复制到目标的函数,大小以字节为单位。
在谷歌搜索时,CopyMemory()
我偶然发现了“ CopyMemory()
vs. ”,并在GameDevmemcpy()
上找到了一个简短的答案:
直接从 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()
)或其他任何可以想象的方式。
最后,OP的附加问题的答案:
我如何将数据读入从共享内存读取的“另一端”的字符串/字节数组中?
读取可以以完全相同的方式完成,除了指向地图视图的指针成为源,本地缓冲区成为目标。但是如何确定大小?这个问题其实更笼统:变长的数据占用了多少字节?C/C++中有两个典型的答案:
- 也可以存储数据的大小(例如 in
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()
,因此 hackstd::string::operator[]()
具有非常量版本。