我的目标是实现以下目标:
我想从磁盘读取文件(假设它是一个图像文件)并将其写入共享内存,以便我可以从另一个进程的共享内存中读取它。 首先,我跟着this msdn tutorial创建了一个包含字符串的简单共享内存实现。它工作正常。
然后我找到了一种从磁盘读取图像的方法。实施如下:
std::ifstream fin("path/to/img.png", std::ios::in | std::ios::binary);
std::ostringstream oss;
oss << fin.rdbuf();
std::string data(oss.str());
现在我有一个std::string
包含我的数据data.length()
表示我读过的文件已成功存储在那里。在msdn示例中,MapViewOfFile
结果的类型为LPTSTR
,因此我找到了一种方法来投射std::string
我必须LPTSTR
,这就是我了解const wchar_t*
。我这样做如下:
std::wstring widestr = std::wstring(data.begin(), data.end());
const wchar_t* widecstr = widestr.c_str();
但如果我现在检查_tcslen(widecstr)
,结果为4
。所以我想我试图做的事情不起作用。我还在另一个问题上找到了这个引用:
注意:std :: string适合保存'二进制'缓冲区,而std :: wstring不是!
(Source)这听起来好像我无法按照我尝试的方式存储文件数据。
所以我的问题是:我是在某个地方犯了错误还是我的方法有缺陷?也许我需要使用另一种文件类型来获得MapViewOfFile
的结果?也许我需要首先将文件加载到另一种类型?
答案 0 :(得分:1)
我不会提供完整的答案,因为我手边没有MCVE。然而,OP要求进一步澄清,并且关于CopyMemory()
我发现了一些值得注意的事情(并且仅仅针对此发表评论有点太长了。)
CopyMemory()
并不特别专注于内存映射文件。它只是一个以大小为单位从源复制数据到目标的函数。
在Google搜索CopyMemory()
时,我偶然发现了{#1}}与CopyMemory()
&#34;并在GameDev找到了一个和简短回答一样好的内容:
直接退出WINBASE.H
memcpy()
然后,直接从WINNT.H
#define CopyMemory RtlCopyMemory
所以,我们在这里:
在标题
中定义<cstring>
#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length))
将
void* memcpy( void* dest, const void* src, std::size_t count );
指向的对象中的count
个字节复制到src
指向的对象。这两个对象都被重新解释为dest
的数组。如果对象重叠,则行为未定义。
对于(可能)重叠的源/目标范围的特殊情况,unsigned char
有一个&#34;兄弟&#34; memmove()
。在这种内存映射文件的情况下,我不相信源和目标可以重叠。因此,memcpy()
可能没问题(甚至可能比memcpy()
更快。)
因此,memmove()
不提供&#34;内存映射文件访问魔术&#34;。这已经发生在另一个函数调用中,它肯定在OP的源代码中但在问题中没有提到:
将文件映射视图映射到调用进程的地址空间。
返回值
如果函数成功,则返回值是映射视图的起始地址。
因此,成功时,CopyMemory()
返回指向文件已映射到的内存的指针。读/写访问可以像之后的任何其他进程内存访问一样完成 - 通过赋值运算符,通过MapViewOfFile()
(或memcpy()
),或者其他任何可想象的内容。
最后,OP的附加问题的答案:
我如何将数据读入&#34;其他&#34;的字符串/字节数组?我从共享内存中读取的那一面?
读取可以完全相同的方式完成,除了指向地图视图的指针成为源并且本地缓冲区成为目标。但如何确定尺寸?这个问题实际上更为通用:具有可变长度的数据占用了多少字节? C / C ++中有两个典型的答案:
CopyMemory()
,std::string
等)在OP的特定情况下,第一种选择可能更合理。因此,有效负载数据(图像)的大小也可能存储在内存映射文件中。在读者方面,首先评估大小(必须具有某种std::vector
类型,因此具有已知的字节数),并且该大小用于复制有效负载数据。
因此,在作家方面,它可能看起来像这样:
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]
相同。在C ++ 17之前,没有data.data()
的非常量版本,因此具有std::string::data()
的hack具有非const版本。