19

I have some struct like this

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

and I have pointer to array of this struct. So, I need to get array from this pointer. I'm tried to using Marshal.PtrToStructure, but i had memory reading error. This is my methode:

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;
}

So, what am i doing wrong ?

1
  • 2
    why is sizeInBytes=Marshal.SizeOf(typeof(TCnt)); instead of being sizeInBytes=Marshal.SizeOf(typeof(MyStruct)); ? Commented Jul 19, 2011 at 12:42

3 Answers 3

19

This function worked for me, assuming that the size of the struct is fixed:

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);
    }
 }
Sign up to request clarification or add additional context in comments.

Comments

5

Two problems. You use TCnt instead of MyStruct in the Marshal.SizeOf() call. Your IntPtr arithmetic cannot work on a 64-bit machine, you must use IntPtr.ToInt64() or cast to (long).

Just getting the wrong IntPtr or length is certainly a possibility too of course. Use Debug + Windows + Memory + Memory 1 and put "pointerToStruct" in the Address box for basic verification.

3 Comments

TCnt is some kind of misprint. Using ntPtr.ToInt64() gives same result
I think the more common term for it is "bug". Anyhoo, enough to get you going I imagine. The Memory window is your ultimate debugging tool.
FYI, C# 4 introduced IntPtr.{Add,Subtract} to make pointer arithmetic less error-prone. See stackoverflow.com/a/5170453/603828
2

Structs in C and C# are not the same thing. One of the differences is that in C# you have to explicitly demand that your struct should be sequentially laid out. If you didn't write [StructLayout(LayoutKind.Sequential)] or [StructLayout(LayoutKind.Explicit)] attribute to your structure I don't believe that you can manage it in this way. Microsoft states that PtrToStructure is to be used to convert structures from unmanaged to managed memory

You should test if adding this attributes to your struct helps, If it doesn't yet help try allocating memory with Marshal.AllocHGlobal(IntPtr) and use Marshal.Copy to init your structure and then try using PtrToStructure. If this works then you can't use PtrToStructure with managed memory

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.