从IntPtr获取struct数组

时间:2011-07-19 12:28:28

标签: c# arrays marshalling intptr

我有一些这样的结构

struct MyStruct
{
    public int field1;
    public int field2;
    public int field3;
}

我有指向此结构数组的指针。 所以,我需要从这个指针获取数组。 我试图使用Marshal.PtrToStructure,但我有内存读取错误。 这是我的方法:

public MyStruct[] GetArrayOfStruct(IntPtr pointerToStruct, int length)
{
    var sizeInBytes = Marshal.SizeOf(typeof(TCnt));
    MyStruct[] output = new MyStruct[length];

    for (int i = 0; i < length; i++)
    {
        IntPtr p = new IntPtr((pointerToStruct.ToInt32() + i * sizeInBytes));

        output[i] = (MyStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(p, typeof(MyStruct));
    }

    return output;
}

那么,我做错了什么?

3 个答案:

答案 0 :(得分:4)

两个问题。您在Marshal.SizeOf()调用中使用TCnt而不是MyStruct。您的IntPtr算术无法在64位计算机上运行,​​您必须使用IntPtr.ToInt64()或强制转换为(长)。

当然,获取错误的IntPtr或长度肯定是可能的。使用Debug + Windows + Memory + Memory 1并在地址框中输入“pointerToStruct”进行基本验证。

答案 1 :(得分:3)

这个功能对我有用,假设结构的大小是固定的

public static void MarshalUnmananagedArray2Struct<T>(IntPtr unmanagedArray, int length, out T[] mangagedArray)
{
    var size = Marshal.SizeOf(typeof(T));
    mangagedArray = new T[length];

    for (int i = 0; i < length; i++)
    {
        IntPtr ins = new IntPtr(unmanagedArray.ToInt64() + i * size);
        mangagedArray[i] = Marshal.PtrToStructure<T>(ins);
    }
 }

答案 2 :(得分:2)

C和C#中的结构不是一回事。其中一个不同之处在于,在C#中,您必须明确要求您的结构应按顺序排列。如果你没写 [StructLayout(LayoutKind.Sequential)][StructLayout(LayoutKind.Explicit)]属于您的结构我不相信您可以通过这种方式管理它。 Microsoft声明PtrToStructure将用于将结构从非托管内存转换为托管内存

您应该测试是否将这些属性添加到您的结构中有帮助,如果它还没有帮助尝试使用Marshal.AllocHGlobal(IntPtr)分配内存并使用Marshal.Copy来初始化您的结构,然后尝试使用{{1} }。如果这样可行,则您无法将PtrToStructure与托管内存一起使用