超级难题:.net 中CreateFileMapping 创建共享内存问题.net中可以通过InteropServices调用unmanaged库的方法CreateFileMapping等来创建和使用共享内存。但是如何将一个对象数组对应到创建的内存块呢?这样一来,内存创建后就不用管了,只要对对象数组进行操作就可以了,请高手指点。-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#region 非托管函数声明
[DllImport("kernel32.dll",EntryPoint="OpenFileMapping",SetLastError=true, CharSet=CharSet.Auto) ]
private static extern IntPtr OpenFileMapping (int dwDesiredAccess, bool bInheritHandle,String lpName );[DllImport("Kernel32.dll",EntryPoint="CreateFileMapping",SetLastError=true,CharSet=CharSet.Auto)]
private static extern IntPtr CreateFileMapping(uint hFile, IntPtr lpAttributes, uint flProtect,uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);[DllImport("Kernel32.dll")]
private static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject,uint dwDesiredAccess, uint dwFileOffsetHigh,uint dwFileOffsetLow, uint dwNumberOfBytesToMap);[DllImport("Kernel32.dll",EntryPoint="UnmapViewOfFile",SetLastError=true,CharSet=CharSet.Auto)]
private static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);[DllImport("kernel32.dll",EntryPoint="CloseHandle",SetLastError=true,CharSet=CharSet.Auto)]
private static extern bool CloseHandle(uint hHandle);[DllImport("kernel32.dll",EntryPoint="GetLastError",SetLastError=true,CharSet=CharSet.Auto)]
private static extern uint GetLastError();
#endregion
struct Money
{
public int EmployeeNo;
public float Salary;
};Money[] g_Money = new Money[100];
for(int i = 0; i < 100; i++)
{
g_Money[i] = new Money();
g_Money[i].EmployeeNo = i;
g_Money[i].Salary = i*i;
}try
{
IntPtr memoryFileHandle = CreateFileMapping(0xFFFFFFFF,IntPtr.Zero,(uint)4,0,(uint)(100*8),"SHARE_MEMORY");
if(memoryFileHandle == IntPtr.Zero)
{
MessageBox.Show("Create Share Memory Failed!");
return;
} g_hMoney = MapViewOfFile(memoryFileHandle,(uint)983071,0,0,(uint)(100*8)); 
if(g_hMoney == IntPtr.Zero)
{
MessageBox.Show("Create Share Memory Failed!");
return;
} int basePos = g_hMoney.ToInt32();
for(int j = 0; j < 100; j++)
{
//我现在的做法,每次将数组对象g_Money一个一个的复制到内存中去
Marshal.StructureToPtr(g_Money[j], (IntPtr)(basePos + j * 8), true);
//我现在的做法,每次将内存中的数据复制到数组对象g_Money中
// g_Money[j] = (Money)Marshal.PtrToStructure((IntPtr)(basePos + j * 8), typeof(Money));
}
}
catch(System.Exception exception)
{
MessageBox.Show(exception.Message);
}我想要得到的效果就是:只要访问g_Money数组就可以直接访问内存,象VC中一样,不要每次对g_Money赋值后再调用Marshal.StructureToPtr修改内存,而每次内存修改后又用Marshal.StructureToPtr读取内存到g_Money来

解决方案 »

  1.   

    You can not do that unless use unmanaged C++ code. Managed Objects are located on local managed heaps.
      

  2.   

    只要访问g_Money数组就可以直接访问内存using System;class a
    {struct Money
    {
    public int EmployeeNo;
    public float Salary;
    };static unsafe void Main(string[] args)
    {
            Money[] g_Money = new Money[100];
            for (int i = 0; i < 100; i++)
            {
                    g_Money[i] = new Money();
                    g_Money[i].EmployeeNo = i;
                    g_Money[i].Salary = i * i;
             }
     fixed(Money* m =g_Money)
    {
       Console.WriteLine(m[0].EmployeeNo);
    }     
    }
    }
      

  3.   

    感谢jiangsheng和The123的回复!The123,我想说的是只要访问g_Money数组就可以直接访问我前面创建的内存,也就是要把g_Money数组和先前创建的共享内存对应起来
      

  4.   

    不可以。传统的(怎么觉得这么别扭)或者说非托管的c/c++里对内存你可以“指哪打哪”,托管的(c#)你不能那么随便了,内存的使用微软的公共语言运行库 (CLR)给你“托管”了。
    你那个Money数组跑在CLR给你“托管”了的内存上,所以你不可能像通常一样直接映射到“调用unmanaged库的方法CreateFileMapping等来创建和使用共享内存”那部分的内存,你也只能通过Marshal.StructureToPtr,Marshal.PtrToStructure的方式来“映射”。
    如果你不是对速度要求特别苛刻的话是没必要用你上面的方式的,你可以把你要操作的数组定义成一个全局变量就可以了。