C#中的结构修改是否会影响非托管内存?

时间:2010-09-02 18:29:58

标签: c# .net struct pinvoke

我的直觉反应是否定的,因为托管和非托管内存是截然不同的,但我不确定.NET Framework是否在幕后为Marshaling做了一些事情。

我认为发生的是: 从我的非托管DLL获取结构时,它与使该调用获取IntPtr然后使用它和Marshal类将结构复制到托管内存(并且对托管内存中的结构所做的更改不会冒泡)相同

我似乎无法在MSDN上的任何地方找到此文档。任何链接都将不胜感激。

以下是我的代码:

[DllImport("mydll.dll", BestFitMapping=false, CharSet=CharSet.Ansi)]
private static extern int GetStruct(ref MyStruct s);

[StructLayout(LayoutKind.Sequential, Pack=0)]
struct MyStruct
{
     public int    Field1;
     public IntPtr Field2;
}

public void DoSomething()
{
      MyStruct s = new MyStruct();
      GetStruct(ref s);

      s.Field1 = 100; //does unmanaged memory now have 100 in Field1 as well?
      s.Field2 = IntPtr.Zero; //does unmanaged memory now have a NULL pointer in field Field2 as well?
}

2 个答案:

答案 0 :(得分:8)

不,P / Invoke marshaller将非托管结构成员值复制到结构的托管版本中。通常,结构的托管版本不以任何方式与其非托管版本兼容。内存布局是不可发现的,CLR用于重新排序字段以使结构更小。编组是必不可少的,你 来创建副本。

使用给定的函数签名无法修改结构,因为您要填写传递给它的内存。函数本身已经复制了结构。但是,您可以使用Field2值,因为它是一个原始指针。如果它指向一个结构,那么用Marshal.PtrToStructure()自己编组。修改它的托管副本,并使用Marshal.StructureToPtr()将其复制回非托管内存。或者直接使用Marshal.ReadXxx()和WriteXxx()访问它。

答案 1 :(得分:0)

CSharp Language Specification.doc pg 26

  

使用new运算符调用struct构造函数,但这并不意味着正在分配内存。结构构造函数不是动态分配对象并返回对它的引用,而是简单地返回结构值本身(通常在堆栈上的临时位置),然后根据需要复制该值。

因为,'struct'后备存储没有什么特别之处,因此人们不会指望在成员作业后面会发生匿名编组操作。