项目中有个场景,vb.net需要调用C++处理后的图片。

原来的处理方案是,C++处理图片后,保存图片到磁盘上,VB.NET再从磁盘上进行读取。

现在想对这个方案进行优化。内存映射文件的形式进行进程间通信是Windows下最高效的方法,因此打算用内存映射文件的形式来连接两个进程。.net端先新建内存映射文件,再调用C++对图片进行处理,处理后的结果写入.net端建好的内存映射文件中,然后.net端再读取内存映射文件。这样处理就可以不用在磁盘上进行读写操作了,节约了IO资源,也更加的高效。

内存映射文件包含虚拟内存中文件的内容。利用文件与内存之间的映射,应用程序(包括多个进程)可以通过直接在内存中进行读写来修改文件。

内存映射文件可以分为两种类型:

①持久内存映射文件:

持久文件是与磁盘上的源文件关联的内存映射文件。在最后一个进程使用完此文件后,数据将保存到磁盘上的源文件中。这些内存映射文件适合用来处理非常大的源文件。

②非持久内存映射文件:

非持久文件是未与磁盘上的源文件关联的内存映射文件。当最后一个进程使用完此文件后,数据将丢失,并且垃圾回收功能将回收此文件。这些文件适用于为进程间通信(IPC)创建共享内存。

我仅仅是想进行进程之间的通信,所以选用了第二种,非持久化内存映射文件。

首先vb端先分配内存空间

Imports System.IO
Imports System.IO.Compression
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Dim mmf As MemoryMappedFile = MemoryMappedFile.CreateNew("img_1", 1024 * 1024)

然后调用c++编译好的命令行可执行文件

Dim p As New System.Diagnostics.Process
p.StartInfo.FileName = "D:\dev\workspaces\outputForMMF\answerSheet.exe"
p.StartInfo.Arguments = imgName & " " & xmlName
p.StartInfo.UseShellExecute = False
p.StartInfo.CreateNoWindow = True
p.Start()
p.WaitForExit()

c++端,对图片文件进行处理后,存入内存映射文件。

char *mmfName = "img_1";
//需要将char转为LPCWSTR
WCHAR wszClassName[20] = {0};
memset(wszClassName,0,sizeof(wszClassName));
MultiByteToWideChar(CP_ACP,0,mmfName,strlen(mmfName)+1,wszClassName,sizeof(wszClassName)/sizeof(wszClassName[0]));  //打开共享的文件对象。
HANDLE m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, wszClassName);
//获得映射视图
char* mmfm_base_address = (char*)MapViewOfFile(m_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, mmfSize);
DWORD error_code;
if(mmfm_base_address == NULL){error_code = GetLastError();if(error_code != SUCCESS){cout<<"error code "<<error_code<<endl;}
}else{//由于C++中对图片的处理使用的是openCV,图片的格式是iplImage。需要将iplImage转为bmp,再存入内存映射文件,这样vb端才能解析出来。//Iplimage *temp;存放的是处理好的图片结果,是全局变量//以下的部分,是把iplimage转为bmp//FILE  *fpw;//变量定义  BITMAPFILEHEADER strHead;BITMAPINFOHEADER strInfo; //初始化头文件。用0来填充内存区域SecureZeroMemory(&strHead, sizeof(strHead));  SecureZeroMemory(&strInfo, sizeof(strInfo));//初始化灰度图调色板RGBQUAD *strPla = (RGBQUAD *)malloc(256*sizeof(RGBQUAD));//调色板的大小为1024字节for (int i1 = 0; i1 < 256; i1++ ){strPla[i1].rgbRed = strPla[i1].rgbGreen = strPla[i1].rgbBlue = i1;strPla[i1].rgbReserved = 0;}//写bitmapFileHeaderstrHead.bfType = 0x4d42;//写入字符"BM"strHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 1024 + (temp->width + 3)/4*4 * temp->height;  strHead.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 1024;//写bitmapInfoHeaderstrInfo.biSize = sizeof(strInfo);strInfo.biHeight = temp->height;strInfo.biWidth = temp->width;strInfo.biPlanes = 1;strInfo.biBitCount = 8;strInfo.biCompression = BI_RGB;/*//保存bmp图片  if((fpw=fopen("M://abc.bmp","wb"))==NULL){  cout<<"create the bmp file error!"<<endl;  return NULL;  }fwrite(&strHead,1,sizeof(strHead),fpw); fwrite(&strInfo,1,sizeof(strInfo),fpw);fwrite(strPla,1,1024,fpw);BYTE *imagedata = NULL;imagedata = (BYTE*)malloc((testBitmap->width + 3)/4*4 * testBitmap->height);for (int k1 = 0; k1 < testBitmap->height; ++k1){for  (int k2 = 0; k2 < testBitmap->width; ++k2){if (getPixelByTemp(testBitmap, k2 , k1)){//黑(*(imagedata + (testBitmap->height - k1 - 1) * ((testBitmap->width + 3)/4*4) + k2)) = 0;}else{//白(*(imagedata + (testBitmap->height - k1 - 1) * ((testBitmap->width + 3)/4*4) + k2)) = 255;}}}fwrite(imagedata,1,(testBitmap->width + 3)/4*4 * testBitmap->height,fpw);fclose(fpw); */CopyMemory(mmfm_base_address, &strHead,sizeof(strHead));char   *imgData = temp->imageData;char *data = NULL;if (temp->nChannels == 3){data = (char*)malloc((temp->width + 3)/4*4 * temp->height);for(int i=0;i<temp->height;i++) for(int j=0;j<(temp->width + 3)/4*4;j++) data[i * ((temp->width + 3)/4*4) + j] = temp->imageData[3*((temp->height - i - 1) * ((temp->width + 3)/4*4) + j)]; CopyMemory(mmfm_base_address + sizeof(strHead), &strInfo,sizeof(strInfo));CopyMemory(mmfm_base_address + sizeof(strHead) + sizeof(strInfo), strPla, 1024);CopyMemory(mmfm_base_address + sizeof(strHead) + sizeof(strInfo) + 1024, data, (temp->width + 3)/4*4 * temp->height);}else if (temp->nChannels == 1){strInfo.biHeight = -strInfo.biHeight;CopyMemory(mmfm_base_address + sizeof(strHead), &strInfo,sizeof(strInfo));CopyMemory(mmfm_base_address + sizeof(strHead) + sizeof(strInfo), strPla, 1024);CopyMemory(mmfm_base_address + sizeof(strHead) + sizeof(strInfo) + 1024, imgData, (temp->width + 3)/4*4 * temp->height);//for(int i=0;i<temp->height;i++) for(int j=0;j<(temp->width + 3)/4*4;j++)//data[i * ((temp->width + 3)/4*4) + j] = temp->imageData[((temp->height - i - 1) * ((temp->width + 3)/4*4) + j)];}else{return false;}/*fwrite(data,1,(testBitmap->width + 3)/4*4 * testBitmap->height,fpw);fclose(fpw);*/ /*FILE    *fpw2;if((fpw2=fopen("M://abc2.bmp","wb"))==NULL){  cout<<"create the bmp2 file error!"<<endl;  return NULL;  }fwrite(mmfm_base_address,1,((testBitmap->width + 3)/4*4 * testBitmap->height + + sizeof(strHead) + sizeof(strInfo) + 1024),fpw2);fclose(fpw2);*///卸载映射UnmapViewOfFile(mmfm_base_address);//关闭内存映射文件CloseHandle(m_hMapFile);
}

完成了C++端的调用后,vb还需读出存入内存映射文件中的图片:

Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("img_1")Using Stream As MemoryMappedViewStream = mmf.CreateViewStream()Dim reader As BinaryReader = New BinaryReader(Stream)Dim bytes As Byte() = reader.ReadBytes(1024 * 1024)'byte()转为bitmapDim newBitmap As Bitmap = Bitmap.FromStream(New MemoryStream(bytes))newBitmap.Save("M:\" & mappingName & ".bmp")End Using
End Using
mmf.Dispose()

这样就完成了VB与C++两个进程之间的通信。

内存映射文件的方式进行进程间通信相关推荐

  1. Java基础:JavaNIO 之 内存映射文件原理

    1. 前言 最近研究Java中内存映射I/O.Java类库中的NIO中的内存映射文件MappedByteBuffer,相对于Java I/O是一个新的功能.特把适合用于处理大文件,在对大文件处理的时候 ...

  2. VC++中使用内存映射文件处理大文件

    引言 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile().ReadFile() ...

  3. 内存映射文件使用详细

    http://www.cppblog.com/woaidongmao/archive/2008/12/26/70439.html 摘要: 本文通过内存映射文件的使用来对大尺寸文件进行访问操作,同时也对 ...

  4. 内存映射文件实现进程间通信

    原理介绍 在Windows平台中,常见的进程间通信机制包括管道.socket.WM_COPYDATA.邮槽等,这些在同一台机器上实现共享数据的最底层机制就是内存映射文件,如果要求低开销和高性能,内存映 ...

  5. java 内存映射文件进程间通讯_[转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile...

    进程间的通信方式有很多种, 上次我们说了最傻瓜的"共享外存/文件"的方法. 那么, 在本文中, 我们即将学习"共享内存"的方式实现进程间的通信, 这是IPC最快 ...

  6. 用内存映射文件实现进程间通信

    使用内存映射文件的一般流程: 由于内存映射文件的一致性,即系统保证在同一文件映射对象的多个视图间保持一致.这可以作为进程通讯的基础,而且在Windows上,同一台机器上共享数据的最底层机制都是内存映射 ...

  7. 8.4 内存映射文件

    与虚拟内存相似,内存映射文件保留了一个地址空间区域,在需要时将它提交到物理存储器.它们之间的不同点是内存映射文件提交到物理存储器的数据来自磁盘上相应的文件,而不是系统页文件.一旦文件被映射,就可以认为 ...

  8. Windows核心编程——》第十七章 内存映射文件 (Memory-Mapped Files)

    1.概览 (1)什么是内存映射文件 内存映射文件是由一个文件到一块内存的映射,使进程虚拟地址空间的某个区域与磁盘上某个文件的部分或全部内容的建立映射. 建立映射后,通过该区域可以直接对被映射的磁盘文件 ...

  9. 数据共享,内存映射文件和虚拟内存,共享内存

    一.内存映射 内存映射文件允许开发人员预定一块地址空间区域并给区域调拨物理存储器.内存映射文件的物理存储器来自磁盘已有的文件,而不是来自系统的页交换文件.一旦把文件映射到地址空间,就可以对它进行访问, ...

最新文章

  1. MySQL 数据库sql语句用关键字作为where条件进行筛选实例演示,mysql建表、查询字段为关键字解决方法
  2. 配置windows驱动开发环境
  3. 1332: 生日日数
  4. 【BZOJ1899】[Zjoi2004]Lunch 午餐 贪心+DP
  5. vue中用的swiper轮播图的用法github的地址
  6. 利用容器来拆分字符串
  7. 四分之一波长传输线应用举例
  8. libevent核心思想:epoll反应堆模型
  9. 新人进群发邮件软件,QQ群潜伏发邮件软件,一进群就收到邮件软件
  10. VTK学习笔记(二十三)vtk空间几何变换
  11. 白帽子黑客:手把手教你如何在Kali使用ibus拼音输入法?
  12. 泰坦尼克:机器从灾难中学习_用于灾难响应的机器学习研究:什么才是好的论文?...
  13. 英文名称:DSPE-PEG10-Mal的试剂分子式是C68H127N2O21P
  14. 腾讯笔试编程题,贪吃的小Q(二分查找)
  15. Java打印101-150之间所有的质数
  16. vue垂直布局_基于 Flex 实现两端对齐垂直布局
  17. Juniper交换机收集日志
  18. Python之心算练习程序
  19. MySQL使用SELECT 语句不加ORDER BY默认是如何排序的?
  20. Java筑基28-泛型

热门文章

  1. 【平面设计基础】08:版式——创意构图
  2. ISP中gamma矫正模块的FPGA设计和仿真
  3. 减半行情会不会来?有何投资机会?2020-03-11
  4. mac 常用软件破解版
  5. python判断数字在不在范围内_在python中检查数字是否在某个范围内(使用循环)?...
  6. 如何开发及维护一个可运营性很高的电商系统
  7. vue3 style
  8. 插值函数总结(下篇之二维插值)
  9. Photoshop蒙版投射
  10. 2D-UNet脑胶质瘤分割BraTs + Pytorch实现