您的位置:首页 > 编程语言 > C#

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

2013-10-29 15:17 435 查看
原文 c#读写共享内存操作函数封装

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

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

[csharp] view plaincopy

/// <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)

[csharp] view plaincopy

/// <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类型的对象。如果需要的话,可以通过显示类型转换转换为需要的类型(例子继续看)。

[csharp] view plaincopy

/// <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来转换指针。

[csharp] view plaincopy

byte[] bytes = new byte[structSize];

arshal.Copy(hVoid, bytes, 0, bytes.Length);

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

注:passiveInfo是NotifyInfo结构体对象。

写共享内存:

[csharp] view plaincopy

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

读共享内存:

第一种情况调用:

[csharp] view plaincopy

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

第二种情况调用:

[csharp] view plaincopy

byte[] bytes = publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), "memName");

passiveInfo = (NotifyInfo)BytesToStuct(bytes, typeof(NotifyInfo));

希望对你有帮助。

转载请标注:http://blog.csdn.net/richerg85
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: