Search code examples
c#c++pointersmarshallingintptr

how to retrieve values from pointer to array of ULONG in C#


Structure in C++:

typedef struct _denom 
    { 
     CHAR       cCurrencyID[3]; 
     int       ulAmount; 
     short     usCount; 
     LPULONG    lpulValues; //pointer to array of ULONGS 
     int      ulCashBox;        
    } DENOMINAT, * LPDENOMINAT; 

Structure in C#:

[ StructLayout( LayoutKind.Sequential, 
CharSet=CharSet.Ansi, Pack=1 ) ] 
 public struct  DENOMINAT 
 { 
   [ MarshalAs( UnmanagedType.ByValArray, SizeConst=3 ) ] 
  public char[] cCurrencyID; 
  public int ulAmount; 
  public short usCount; 
  public IntPtr lpulValues; 
  public int ulCashBox;     
} 

lpulValues is a pointer to array of ulongs and its array size is based on the usCount for eg :if uscount is 5 then in C++ it would be lpulValues = new ULONG[usCount];.

I can easily get the array values in C++ which is not been possible in C#.I dont understand how to get the array values through IntPtr. Thanks in advance.


Solution

  • Important thing

    In Windows, in C/C++, sizeof(long) == sizeof(int). So sizeof(C-long) == sizeof(C#-int). See https://stackoverflow.com/a/9689080/613130

    You should be able to do:

    var denominat = new DENOMINAT();
    
    var uints = new uint[denominat.usCount];
    Marshal.Copy(denominat.lpulValues, (int[])(Array)uints, 0, uints.Length);
    

    Note that we cheat a little, casting the uint[] to a int[], but it is legal, because they differ only for the sign (see https://stackoverflow.com/a/593799/613130)

    I don't think you can do it automatically with the .NET PInvoke marshaler.

    To display the array:

    for (int i = 0; i < uints.Length; i++)
    {
        Console.WriteLine(uints[i]);
    }