我的直觉反应是否定的,因为托管和非托管内存是截然不同的,但我不确定.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?
}
答案 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'后备存储没有什么特别之处,因此人们不会指望在成员作业后面会发生匿名编组操作。