原文 c#读写共享内存操作函数封装

c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂。

现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方面则是做个备份吧。

[csharp] view plaincopy

  1. /// <summary>
  2. /// 写共享内存
  3. /// </summary>
  4. /// <param name="structSize">需要映射的文件的字节数量</param>
  5. /// <param name="obj">映射对象(简单类型、结构体等)</param>
  6. /// <param name="fileName">文件映射对象的名称</param>
  7. /// <param name="windowName">发送消息的窗口句柄</param>
  8. /// <param name="Msg">发送消息</param>
  9. /// <returns></returns>
  10. public static int WriteToMemory(uint structSize, Object obj, string fileName, string windowName, uint Msg)
  11. {
  12. IntPtr hShareMemoryHandle = IntPtr.Zero;
  13. IntPtr hVoid = IntPtr.Zero;
  14. //判断参数的合法性
  15. if (structSize > 0 && fileName.Length > 0)
  16. {
  17. hShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)structSize, fileName);
  18. if (hShareMemoryHandle == IntPtr.Zero)
  19. {
  20. //创建共享内存失败,记log
  21. MessageBox.Show("创建共享内存失败"+publicInfo.GetLastError().ToString());
  22. return -2;
  23. }
  24. else
  25. {
  26. if (ERROR_ALREADY_EXISTS == GetLastError())
  27. {
  28. //共享内存已经存在,记log
  29. MessageBox.Show("共享内存已经存在");
  30. return -3;
  31. }
  32. }
  33. hVoid = MapViewOfFile(hShareMemoryHandle, FILE_MAP_WRITE, 0, 0, structSize);
  34. if (hVoid == IntPtr.Zero)
  35. {
  36. CloseHandle(hShareMemoryHandle);
  37. //文件映射失败,记log
  38. MessageBox.Show("文件映射失败");
  39. return -4;
  40. }
  41. Marshal.StructureToPtr(obj, hVoid, false);
  42. //发送消息,通知接收
  43. IntPtr handle = FindWindow(null, windowName.Trim());
  44. if (handle == IntPtr.Zero)
  45. {
  46. //查找窗口失败,记log
  47. MessageBox.Show("查找窗口失败");
  48. return -5;
  49. }
  50. else
  51. {
  52. if (PostMessage(handle, (uint)Msg, 0, 0))
  53. {
  54. //发送消息成功
  55. //MessageBox.Show("写共享内存,通知发送消息成功");
  56. }
  57. }
  58. }
  59. else
  60. {
  61. //参数不合法,记log
  62. MessageBox.Show("共享内存已经存在");
  63. return -1;
  64. }
  65. return 0;
  66. }

写共享内存函数并没有什么需要说明,完全按照:

创建共享内存文件(CreateFileMapping)---》映射文件视图到调用进程的地址空间(MapViewOfFile)---》写数据到共享内存(Marshal.StructureToPtr)----》发送消息通知需要读共享内存的窗口(PostMessage)

[csharp] view plaincopy

  1. /// <summary>
  2. /// 读共享内存
  3. /// </summary>
  4. /// <param name="structSize">需要映射的文件的字节数量</param>
  5. /// <param name="type">类型</param>
  6. /// <param name="fileName">文件映射对象的名称</param>
  7. /// <returns>返回读到的映射对象</returns>
  8. public static Object ReadFromMemory(uint structSize, Type type, string fileName)
  9. {
  10. IntPtr hMappingHandle = IntPtr.Zero;
  11. IntPtr hVoid = IntPtr.Zero;
  12. hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);
  13. if (hMappingHandle == IntPtr.Zero)
  14. {
  15. //打开共享内存失败,记log
  16. MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());
  17. return null;
  18. }
  19. hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);
  20. if (hVoid == IntPtr.Zero)
  21. {
  22. //文件映射失败,记log
  23. MessageBox.Show("文件映射失败——读共享内存");
  24. return null;
  25. }
  26. Object obj = Marshal.PtrToStructure(hVoid, type);
  27. if (hVoid != IntPtr.Zero)
  28. {
  29. UnmapViewOfFile(hVoid);
  30. hVoid = IntPtr.Zero;
  31. }
  32. if (hMappingHandle != IntPtr.Zero)
  33. {
  34. CloseHandle(hMappingHandle);
  35. hMappingHandle = IntPtr.Zero;
  36. }
  37. return obj;
  38. }

读共享内存,上边代码是一种方式,这里是传入一个Type类型,这样就确保可以传入任何类型。当读到共享内存的数据时,采用

public static object PtrToStructure(IntPtr ptr, Type structureType);

函数,把非托管指针(共享内存获得的指针)转换为需要转换的Type类型的对象。如果需要的话,可以通过显示类型转换转换为需要的类型(例子继续看)。

[csharp] view plaincopy

  1. /// <summary>
  2. /// 读共享内存
  3. /// </summary>
  4. /// <param name="structSize">需要映射的文件的字节数量</param>
  5. /// <param name="type">类型</param>
  6. /// <param name="fileName">文件映射对象的名称</param>
  7. /// <returns>返回读到的映射字节数据</returns>
  8. public static byte[] ReadFromMemory(uint structSize, Type type, string fileName)
  9. {
  10. IntPtr hMappingHandle = IntPtr.Zero;
  11. IntPtr hVoid = IntPtr.Zero;
  12. hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);
  13. if (hMappingHandle == IntPtr.Zero)
  14. {
  15. //打开共享内存失败,记log
  16. MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());
  17. return null;
  18. }
  19. hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);
  20. if (hVoid == IntPtr.Zero)
  21. {
  22. //文件映射失败,记log
  23. MessageBox.Show("文件映射失败——读共享内存");
  24. return null;
  25. }
  26. //Object obj = Marshal.PtrToStructure(hVoid, type);
  27. byte[] bytes = new byte[structSize];
  28. Marshal.Copy(hVoid, bytes, 0, bytes.Length);
  29. if (hVoid != IntPtr.Zero)
  30. {
  31. UnmapViewOfFile(hVoid);
  32. hVoid = IntPtr.Zero;
  33. }
  34. if (hMappingHandle != IntPtr.Zero)
  35. {
  36. CloseHandle(hMappingHandle);
  37. hMappingHandle = IntPtr.Zero;
  38. }
  39. return bytes;
  40. }

此代码和第一个读共享内存不同的是,采用byte[]读需要的共享内存。使用托管类中的Copy来转换指针。

[csharp] view plaincopy

  1. byte[] bytes = new byte[structSize];
  2. arshal.Copy(hVoid, bytes, 0, bytes.Length);

调用简单例子部分代码如下:

注:passiveInfo是NotifyInfo结构体对象。

写共享内存:

[csharp] view plaincopy

  1. int iRet = publicInfo.WriteToMemory((uint)Marshal.SizeOf(passiveInfo),(Object)passiveInfo, "memName","FormMsg",(uint)publicInfo.WM_NOTIFY);

读共享内存:

第一种情况调用:

[csharp] view plaincopy

  1. passiveInfo = (NotifyPassiveInfo)publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), typeof(NotifyPassiveInfo), publicInfo.SN_PASSIVEINFO);

第二种情况调用:

[csharp] view plaincopy

  1. byte[] bytes = publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), "memName");
  2. passiveInfo = (NotifyInfo)BytesToStuct(bytes, typeof(NotifyInfo));

希望对你有帮助。

转载请标注:http://blog.csdn.net/richerg85

c#读写共享内存操作函数封装的更多相关文章

  1. 共享内存操作类(C#源码)

    原文 http://blog.csdn.net/yefanqiu/article/details/1717458 VC++的共享内存操作代码实现起来相对比较容易,但是用C#语言来实现,就有一定难度,由 ...

  2. c++ void,内存操作函数

    void的含义 void的字面意思是“无类型”, void * 则为“无类型指针”, void * 可以指向任何类型的数据 void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变 ...

  3. Delphi中复制带有String的记录结构时不能使用Move之类的内存操作函数

    请看下面的代码: program TestRecord; {$APPTYPE CONSOLE} uses  SysUtils,  Math; type  TRecordA = record    Na ...

  4. 内存操作函数memmove,memcpy,memset

    通过字符串的学习,我们知道字符串操作函数的操作对象是字符串,并且它的结束标志是结束符\0,当然这个说的是不 受限制的字符串函数.然而当我们想要将一段内存的数据复制到另一块内存时,我们不能使用字符串操作 ...

  5. 共享内存:mmap函数实现

    内存映射的应用: 以页面为单位,将一个普通文件映射到内存中,通常在须要对文件进行频繁读写时使用,这样用内存读写代替I/O读写,以获得较高的性能; 将特殊文件进行匿名内存映射,能够为关联进程提供共享内存 ...

  6. C语言中内存操作函数

      一.malloc/calloc 名称: Malloc/calloc 功能: 动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(s ...

  7. 自己实现内存操作函数memset(),memcmp(),memcpy(),memmove()

    1.memset()内存设置函数(初始化) void *my_memset(void* dest, int c, size_t count) { assert(dest != NULL); char  ...

  8. 【转】C内存操作函数

    一.malloc/calloc 名称: Malloc/calloc 功能:  动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(si ...

  9. c语言学习之基础知识点介绍(十九):内存操作函数

    一.malloc函数 /* 首先需要导入头文件 #include <stdlib.h> malloc void* malloc(n); n是字节大小 开辟堆空间,开辟的字节数以n为准 返回 ...

随机推荐

  1. <转>ASP.NET学习笔记之在ASP.NET MVC中使用DropDownList

    看到一篇关于dropdownlist的用法很好的阐述,比较清楚,留着,防止以后自己不记得,还可以瞅瞅. 在ASP.NET MVC中,尽管我们可以直接在页面中编写HTML控件,并绑定控件的属性,但更方便 ...

  2. STL模板_智能指针概念

    一.智能指针1.类类型对象,在其内部封装了一个普通指针.当智能指针对象因离开作用域而被析构时,其析构函数被执行,通过其内部封装的普通指针,销毁该指针的目标对象,避免内存泄露.2.为了表现出和普通指针一 ...

  3. C++ this 指针

    类的(非静态)成员函数具有一个附加的隐含形参,即指向该类对象的一个指针.这个隐含形参命名为this,与调用成员函数的对象绑定在一起.成员函数不能定义this形参,而是由编译器隐含地定义.成员函数的函数 ...

  4. Collections之sort的两个方法(自然排序和自定义比较器排序)

    Collections是个服务于Collection的工具类(静态的),它里面定义了一些集合可以用到的方法. 本文演示了Collections类里sort()的两个方法.第一种只需传入被排序的集合,便 ...

  5. 个人笔记mysql游标

    经过测试,mysql游标是无法读取自定义函数计算的结构,mysql自带的函数计算值是可以读取的.

  6. NETTY 编码器介绍

    1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 反之,解码(Decod ...

  7. software testing homework2

    一.Checkstyle安装及使用 1.checkstyle插件包:http://sourceforge.net/projects/eclipse-cs/ checkstyle.xml配置文件:htt ...

  8. 投资新兴市场和细分市场 good

    新兴市场对程序员来说,就是一种新的语言.一个新的平台.一套新的框架.新兴市场因为刚刚兴起,所以几乎所有人都在同一个起跑线,特别适合后进者.我认识从一个2011年开始学习iOS开发的同学,他能能力中等, ...

  9. STL 全特化/偏特化

    template<class T> class Compare { public: static bool isEqual(const T& lh,const T& rh) ...

  10. HDU 4957 Poor Mitsui

    题解:记答案为ans,已知,对一个确定的顺序,计算所用的时间长短就是从最后向前计算,计算方法如下: ans+=(p[i].b+ans*p[i].a)/(v-p[i].a) 那么,应该如何调整顺序使得答 ...