How to Marshal an C++ Struct Array using IntPtr RRS feed

  • Question

  • I have a following code in a C++ DLL
    typedef struct _MYPOINT
        int nX;
        int nY;
    } MYPOINT;
    extern "C"  __declspec(dllexport) void ModifyPointArray (int nSize, MYPOINT *ptArr[]) 
        for ( int nI = 0; nI < nSize; nI++ )
    	ptArr[nI]->nX +=5;
    	ptArr[nI]->nY +=5;


    I have defined a Wrapper Class for the DLL something like this.
    namespace MarshalDemo
        public class MyPoint
            public int nX;
            public int nY;
            public MyPoint()
                this.nX = 0;
                this.nY = 0;
            public MyPoint(int x, int y)
                this.nX = x;
                this.nY = y;
        public static class MarshalDllWrapper
          public static extern void ModifyPointArray(int nSize, IntPtr [] arrPts);
    What I have tried:

    Now i am trying to call this function using Marshalling using IntPtr, my .NET client code (C#) is something like this.
    MyPoint[] pointArr = { new MyPoint(5, 6), new MyPoint(7, 8), new MyPoint(9, 10) };
    int nCount = pointArr.Length;
    IntPtr[] ptrArr = new IntPtr[nCount];
    for (int nI=0; nI< nCount; nI++)
         ptrArr[nI] = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(MyPoint)));
         Marshal.StructureToPtr(pointArr[nI], ptrArr[nI], true);
    MarshalDllWrapper.DisplayPointArray(nCount, ptrArr);
    MyPoint[] pointArr2 = new MyPoint[nCount];
    for (int nI = 0; nI < nCount; nI++)
         Marshal.PtrToStructure(ptrArr[nI], pointArr2[nI]);

    I am getting an Error on line
    //F:\VS2010\VCS2010\Marshalling\MarshalDll\MarshalDllClient\frmMarshalDemo.cs:line XXX
    Marshal.PtrToStructure(ptrArr[nI], pointArr2[nI]);

    with Error Message
    System.ArgumentNullException: Value cannot be null.
    Parameter name: structure
       at System.Runtime.InteropServices.Marshal.PtrToStructureHelper(IntPtr ptr, Object structure, Boolean allowValueClasses)
       at System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr ptr, Object structure)
       at MarshalDemo.frmMarshalDemo.btnPointArray_Click(Object sender, 
    EventArgs e) in 
    F:\VS2010\VCS2010\Marshalling\MarshalDll\MarshalDllClient\frmMarshalDemo.cs:line XXX 

    PS : I know if i write a Wrapper something like this.

    public static extern void ModifyPointStructArray(int nSize, [In, Out] MyPoint[] arrStruc);

    it works like a breeze, but i want to do with IntPtr, am i doing something conceptually wrong ?

    What I am doing wrong ?
    Any Help will will apreciated.



    Praveen K.

    • Moved by Richard MuellerMVP Tuesday, December 3, 2019 1:52 PM Not a Profile/Recognition question
    Tuesday, December 3, 2019 1:47 PM


  • From https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/single-dimensional-arrays

    Value Type and Reference Type Arrays

    Consider the following array declaration:

    SomeType[] array4 = new SomeType[10];

    The result of this statement depends on whether SomeType is a value type or a reference type. If it is a value type, the statement creates an array of 10 elements, each of which has the type SomeType. If SomeType is a reference type, the statement creates an array of 10 elements, each of which is initialized to a null reference.

    Try this -

    MyPoint[] pointArr2 = { new MyPoint(), new MyPoint(), new MyPoint() };

    instead of

    MyPoint[] pointArr2 = new MyPoint[nCount];
    Also, you should specify CallingConvention = CallingConvention.Cdecl in [DllImport].

    • Edited by RLWA32 Tuesday, December 3, 2019 3:03 PM
    • Marked as answer by Praveen K. Katiyar Tuesday, December 3, 2019 3:33 PM
    Tuesday, December 3, 2019 3:01 PM

All replies