从IntPtr编组结构数组 - 只有正确的第一价值编组

时间:2016-02-27 11:56:03

标签: c# marshalling

我将一个结构数组的地址传递给外部程序的C#DLL。

我认为我会首先做一个简单的测试,以便通过尝试将指针编组到C#端的结构数组中来查看该方法是否有效。

给出以下结构:

[StructLayout(LayoutKind.Sequential)]
struct TestStruct
{
    public int id;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string someString;
}

以下代码尝试读取struct数组(直到for循环之前的部分只是为了模拟从其他程序传递的指针):

TestStruct[] testStructs = new TestStruct[3];
testStructs[0].id = 1;
testStructs[0].someString = "Value 1";
testStructs[1].id = 2;
testStructs[1].someString = "Value 2";
testStructs[2].id = 3;
testStructs[2].someString = "Value 3";

int size = Marshal.SizeOf(testStructs[0]);
IntPtr ptrFirst = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(testStructs[0], ptrFirst, true);

long ptrAddrLong = ptrFirst.ToInt64();

for (int i = 0; i < testStructs.Length; i++) {
    IntPtr thisPtr = new IntPtr(ptrAddrLong);
    TestStruct testStruct = Marshal.PtrToStructure<TestStruct>(thisPtr);
    ptrAddrLong += size;
}

任何人都可以解释为什么,当我通过for循环调试时,只有第一个testStruct项正确地从指针编组?所有后续项目都包含字段中的垃圾,因为在第一次迭代后,指针地址显示不正确。

第一次迭代: enter image description here

第二次迭代: enter image description here

尺寸报告为36,这似乎是正确的。

我尝试使用显式布局,但这没有任何区别。

由于

1 个答案:

答案 0 :(得分:0)

为什么你认为Marshal.StructureToPtr编组的东西比你告诉它要编组的更多?

Marshal.StructureToPtr(testStructs[0], ptrFirst, true);单个 TestStruct编组到ptrFirst的内存中。

它基本上只是一个智能内存副本,它考虑了所有这些编组属性。

P.S。:并考虑到ptrFirst的内存最多可以保留Marshal.SizeOf(testStructs[0])。所以你不能(至少没有冒一些nasty memory access problem的风险)读取ptrFirst + size后面的内存。