c#读写共享内存操作函数封装
c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂。
现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方面则是做个备份吧。
- /// <summary>
- /// 写共享内存
- /// </summary>
- /// <param name="structSize">需要映射的文件的字节数量</param>
- /// <param name="obj">映射对象(简单类型、结构体等)</param>
- /// <param name="fileName">文件映射对象的名称</param>
- /// <param name="windowName">发送消息的窗口句柄</param>
- /// <param name="Msg">发送消息</param>
- /// <returns></returns>
- public static int WriteToMemory(uint structSize, Object obj, string fileName, string windowName, uint Msg)
- {
- IntPtr hShareMemoryHandle = IntPtr.Zero;
- IntPtr hVoid = IntPtr.Zero;
- //判断参数的合法性
- if (structSize > 0 && fileName.Length > 0)
- {
- hShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)structSize, fileName);
- if (hShareMemoryHandle == IntPtr.Zero)
- {
- //创建共享内存失败,记log
- MessageBox.Show("创建共享内存失败"+publicInfo.GetLastError().ToString());
- return -2;
- }
- else
- {
- if (ERROR_ALREADY_EXISTS == GetLastError())
- {
- //共享内存已经存在,记log
- MessageBox.Show("共享内存已经存在");
- return -3;
- }
- }
- hVoid = MapViewOfFile(hShareMemoryHandle, FILE_MAP_WRITE, 0, 0, structSize);
- if (hVoid == IntPtr.Zero)
- {
- CloseHandle(hShareMemoryHandle);
- //文件映射失败,记log
- MessageBox.Show("文件映射失败");
- return -4;
- }
- Marshal.StructureToPtr(obj, hVoid, false);
- //发送消息,通知接收
- IntPtr handle = FindWindow(null, windowName.Trim());
- if (handle == IntPtr.Zero)
- {
- //查找窗口失败,记log
- MessageBox.Show("查找窗口失败");
- return -5;
- }
- else
- {
- if (PostMessage(handle, (uint)Msg, 0, 0))
- {
- //发送消息成功
- //MessageBox.Show("写共享内存,通知发送消息成功");
- }
- }
- }
- else
- {
- //参数不合法,记log
- MessageBox.Show("共享内存已经存在");
- return -1;
- }
- return 0;
- }
写共享内存函数并没有什么需要说明,完全按照:
创建共享内存文件(CreateFileMapping)---》映射文件视图到调用进程的地址空间(MapViewOfFile)---》写数据到共享内存(Marshal.StructureToPtr)----》发送消息通知需要读共享内存的窗口(PostMessage)
- /// <summary>
- /// 读共享内存
- /// </summary>
- /// <param name="structSize">需要映射的文件的字节数量</param>
- /// <param name="type">类型</param>
- /// <param name="fileName">文件映射对象的名称</param>
- /// <returns>返回读到的映射对象</returns>
- public static Object ReadFromMemory(uint structSize, Type type, string fileName)
- {
- IntPtr hMappingHandle = IntPtr.Zero;
- IntPtr hVoid = IntPtr.Zero;
- hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);
- if (hMappingHandle == IntPtr.Zero)
- {
- //打开共享内存失败,记log
- MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());
- return null;
- }
- hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);
- if (hVoid == IntPtr.Zero)
- {
- //文件映射失败,记log
- MessageBox.Show("文件映射失败——读共享内存");
- return null;
- }
- Object obj = Marshal.PtrToStructure(hVoid, type);
- if (hVoid != IntPtr.Zero)
- {
- UnmapViewOfFile(hVoid);
- hVoid = IntPtr.Zero;
- }
- if (hMappingHandle != IntPtr.Zero)
- {
- CloseHandle(hMappingHandle);
- hMappingHandle = IntPtr.Zero;
- }
- return obj;
- }
读共享内存,上边代码是一种方式,这里是传入一个Type类型,这样就确保可以传入任何类型。当读到共享内存的数据时,采用
public static object PtrToStructure(IntPtr ptr, Type structureType);
函数,把非托管指针(共享内存获得的指针)转换为需要转换的Type类型的对象。如果需要的话,可以通过显示类型转换转换为需要的类型(例子继续看)。
- /// <summary>
- /// 读共享内存
- /// </summary>
- /// <param name="structSize">需要映射的文件的字节数量</param>
- /// <param name="type">类型</param>
- /// <param name="fileName">文件映射对象的名称</param>
- /// <returns>返回读到的映射字节数据</returns>
- public static byte[] ReadFromMemory(uint structSize, Type type, string fileName)
- {
- IntPtr hMappingHandle = IntPtr.Zero;
- IntPtr hVoid = IntPtr.Zero;
- hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);
- if (hMappingHandle == IntPtr.Zero)
- {
- //打开共享内存失败,记log
- MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());
- return null;
- }
- hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);
- if (hVoid == IntPtr.Zero)
- {
- //文件映射失败,记log
- MessageBox.Show("文件映射失败——读共享内存");
- return null;
- }
- //Object obj = Marshal.PtrToStructure(hVoid, type);
- byte[] bytes = new byte[structSize];
- Marshal.Copy(hVoid, bytes, 0, bytes.Length);
- if (hVoid != IntPtr.Zero)
- {
- UnmapViewOfFile(hVoid);
- hVoid = IntPtr.Zero;
- }
- if (hMappingHandle != IntPtr.Zero)
- {
- CloseHandle(hMappingHandle);
- hMappingHandle = IntPtr.Zero;
- }
- return bytes;
- }
此代码和第一个读共享内存不同的是,采用byte[]读需要的共享内存。使用托管类中的Copy来转换指针。
- byte[] bytes = new byte[structSize];
- arshal.Copy(hVoid, bytes, 0, bytes.Length);
调用简单例子部分代码如下:
注:passiveInfo是NotifyInfo结构体对象。
写共享内存:
- int iRet = publicInfo.WriteToMemory((uint)Marshal.SizeOf(passiveInfo),(Object)passiveInfo, "memName","FormMsg",(uint)publicInfo.WM_NOTIFY);
读共享内存:
第一种情况调用:
- passiveInfo = (NotifyPassiveInfo)publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), typeof(NotifyPassiveInfo), publicInfo.SN_PASSIVEINFO);
第二种情况调用:
- byte[] bytes = publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), "memName");
- passiveInfo = (NotifyInfo)BytesToStuct(bytes, typeof(NotifyInfo));
希望对你有帮助。
转载请标注:http://blog.csdn.net/richerg85
c#读写共享内存操作函数封装的更多相关文章
- 共享内存操作类(C#源码)
原文 http://blog.csdn.net/yefanqiu/article/details/1717458 VC++的共享内存操作代码实现起来相对比较容易,但是用C#语言来实现,就有一定难度,由 ...
- c++ void,内存操作函数
void的含义 void的字面意思是“无类型”, void * 则为“无类型指针”, void * 可以指向任何类型的数据 void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变 ...
- Delphi中复制带有String的记录结构时不能使用Move之类的内存操作函数
请看下面的代码: program TestRecord; {$APPTYPE CONSOLE} uses SysUtils, Math; type TRecordA = record Na ...
- 内存操作函数memmove,memcpy,memset
通过字符串的学习,我们知道字符串操作函数的操作对象是字符串,并且它的结束标志是结束符\0,当然这个说的是不 受限制的字符串函数.然而当我们想要将一段内存的数据复制到另一块内存时,我们不能使用字符串操作 ...
- 共享内存:mmap函数实现
内存映射的应用: 以页面为单位,将一个普通文件映射到内存中,通常在须要对文件进行频繁读写时使用,这样用内存读写代替I/O读写,以获得较高的性能; 将特殊文件进行匿名内存映射,能够为关联进程提供共享内存 ...
- C语言中内存操作函数
一.malloc/calloc 名称: Malloc/calloc 功能: 动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(s ...
- 自己实现内存操作函数memset(),memcmp(),memcpy(),memmove()
1.memset()内存设置函数(初始化) void *my_memset(void* dest, int c, size_t count) { assert(dest != NULL); char ...
- 【转】C内存操作函数
一.malloc/calloc 名称: Malloc/calloc 功能: 动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(si ...
- c语言学习之基础知识点介绍(十九):内存操作函数
一.malloc函数 /* 首先需要导入头文件 #include <stdlib.h> malloc void* malloc(n); n是字节大小 开辟堆空间,开辟的字节数以n为准 返回 ...
随机推荐
- CentOS 安装Node.js
先安装gcc-c++编译环境和openssl yum install gcc-c++ openssl-devel 然后 下载包并解压 cd /usr/local/src wget http://nod ...
- SQL Server 使用ROW_NUMBER()进行分页
代码示例: WITH domain AS(SELECT ROW_NUMBER() OVER(ORDER BY ID DESC) ids,* FROM dbo.DomainInfo) SELECT * ...
- USACO Section 5.1 Musical Themes(枚举)
直接枚举O(n^3)会TLE,只要稍微加点优化,在不可能得到更优解时及时退出.其实就是道水题,虽说我提交了6次才过= =..我还太弱了 -------------------------------- ...
- Struts学习之流程汇总
struts2 架构图如下图所示: 依照上图,我们可以看出一个请求在struts的处理大概有如下步骤: 1.客户端初始化一个指向Servlet容器(例如Tomcat)的请求: 2.这个请求经过一系列的 ...
- 一周学会Mootools 1.4中文教程:(1)Dom选择器
利器: 君欲善其事须先利其器,好吧因为我们的时间比较紧迫,只有六天而已,那么六天的时间用死记硬背的方式学会Mt犹如天方夜谭,因此我们需要借鉴一下Editplus的素材栏帮我们记忆就好了,当我们需要用到 ...
- poj 3252 Round Numbers 数位dp
题目链接 找一个范围内二进制中0的个数大于等于1的个数的数的数量.基础的数位dp #include<bits/stdc++.h> using namespace std; #define ...
- Qt程序打包成exe可执行文件图文教程(图文并茂,且用到了filepack)
很多Qt爱好者想发布自己的Qt软件,但却发现在其他没有安装Qt SDK的机器上无法运行,这就是本文想要说明的问题.现在网上大部分软件都要发布自己开发的应用程序,都会打包到exe文件中,待安装完exe文 ...
- openstack nova修改实例路径,虚拟磁盘路径
#实例路径 --instances_path=$state_path/instances #日志的目录 --logdir=/var/log/nova #nova的目录 --state_path=/va ...
- 在美国,一名 Uber 司机能赚多少?
在美国,Uber 司机是最热门的职业.有了 uberX,任何有车一族都能成为司机.Uber 让我们很容易成为司机. 虽然 Uber 做不到赚得盆满钵满,但对于水深火热的司机这一行来说,多了许多盈利机会 ...
- nyist 202 红黑树(二叉树中序遍历)
旋转对中序遍历没有影响,直接中序输出即可. #include <iostream> #include <cstdio> using namespace std; int n; ...