现在的位置: 首页 > 综合 > 正文

.Net P/Invoke 非托管内存的访问

2013年08月06日 ⁄ 综合 ⁄ 共 1514字 ⁄ 字号 评论关闭

.Net P/Invoke 非托管内存的访问


[ 2007-10-17 11:50:16 | 作者: Admin
]


字体大小:

|

|

在使用P/Invoke时经常需要分配、释放非托管内存,实际上.Net的Marshal类提供了非常全面的功能,可以按照开发者的意愿去组织内存结构,只是使用上大大不如C++方便了。下面举例说明。

C++的结构:
  struct t_Inner
  {
    char* name;
    int type;
  };
  struct t_Outer
  {
    t_Inner* inners; //t_Inner结构的数组
    int count; //t_Inner数组的长度
  };

  void TestStruct(t_Outer* outer); //此函数将生成outer结构的具体内容

C#调用
首先定义结构:

  [StructLayout(LayoutKind.Sequential)]
  public struct t_Inner
  {
    public IntPtr name;
    public int type;
  };

  [StructLayout(LayoutKind.Sequential)]
  public struct t_Outer
  {
    public IntPtr inners;
    public int count;
  };

引用C++的函数
    [DllImport(@"D:/test.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
    public extern static int TestStruct(ref t_Outer outer);

调用函数:
    public void TestStruct()
    {
      t_Outer outer = new t_Outer();
      IntPtr strPtr, innerPtr;

      outer.count = 3;
      outer.inners = Marshal.AllocHGlobal(3 * Marshal.SizeOf(typeof(t_Inner)));

      for (int i = 0; i < outer.count; i++)
      {
        innerPtr = Marshal.ReadIntPtr(outer.inners, Marshal.SizeOf(typeof(t_Inner)) * i);
        strPtr = Marshal.AllocHGlobal(BufferLen.BASMAX_FILE_NAME);
        Marshal.WriteIntPtr(outer.inners, Marshal.SizeOf(typeof(t_Inner)) * i, strPtr);
      }

      BaSFunctions.TestStruct(ref outer);

      for (int i = 0; i < outer.count; i++)
      {
        strPtr = Marshal.ReadIntPtr(outer.inners, Marshal.SizeOf(typeof(t_Inner)) * i);
        string str = Marshal.PtrToStringAuto(strPtr);
        Debug.WriteLine(str);
      }
    }

在内存分配上可以采用.Net分配并释放内存,或者C++代码分配并释放内存,这两种方法各有优缺点。这里采用的是.Net分配并释放非托管内存的方法。

抱歉!评论已关闭.