Answered by:
How to Marshal an C++ Struct Array using IntPtr

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 { [StructLayout(LayoutKind.Sequential)] 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 { [DllImport("MarshalDll.dll")] 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]); Marshal.FreeCoTaskMem(ptrArr[nI]); }
I am getting an Error on line
//F:\VS2010\VCS2010\Marshalling\MarshalDll\MarshalDllClient\frmMarshalDemo.cs:line XXXMarshal.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.
Thanks.
Praveen.
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
Answers
-
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:
C#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 typeSomeType
. IfSomeType
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
-
This forum is for questions and discussions about the Profile and Recognition system.
I would ask here:
https://social.msdn.microsoft.com/Forums/en-us/home?forum=vcgeneral
Richard Mueller - MVP Enterprise Mobility (Identity and Access)
- Proposed as answer by Dave PatrickMVP Tuesday, December 3, 2019 2:24 PM
Tuesday, December 3, 2019 1:51 PM -
Hello,
for C# you should ask here: https://social.msdn.microsoft.com/Forums/vstudio/en-us/home?forum=csharpgeneral
Tuesday, December 3, 2019 2:03 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:
C#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 typeSomeType
. IfSomeType
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