1

I am trying to use pinvoke to marshal a C structure to C#. While I am able to marshal an intptr I cannot find the syntax to marshal a double pointer. Both the int pointer and double pointer are used on the C side to alloc an array of ints or doubles.

Here is the C struct:

struct xyz
{
      int *np;  // an int pointer works fine
      double *foo;
};

And here is the c# class:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class xyz
{
    Intptr np;  // works fine
            // double *foo   ?? 
   }

I am unable to find any instructions on how to marc

PaeneInsula
  • 2,010
  • 3
  • 31
  • 57
  • IntPtr is just a pointer: up to void*; so you can try marshaling "double* foo" as "IntPtr foo"; – Dmitry Bychenko Sep 03 '13 at 12:22
  • IntPtr doesn't mean "pointer to integer". MSDN: The IntPtr type is designed to be an integer whose size is platform-specific. It can point to any data. – Alex F Sep 03 '13 at 12:45
  • Clarification: the C code is doing all the alloc/free of memory, so the c# side is blissfully unaware of all of that. – PaeneInsula Sep 03 '13 at 15:10

2 Answers2

1

Check out this description for what an IntPtr is. Have you tried using:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class xyz
{
    IntPtr np;
    IntPtr foo;
}
Community
  • 1
  • 1
Dutts
  • 5,781
  • 3
  • 39
  • 61
0

You seem to think that IntPtr is a pointer to an int. That is not the case. An IntPtr is an integer that is the same width as a pointer. So IntPtr is 32 bits wide on x86, and 64 bits wide on x64. The documentation makes all this clear.

The closest equivalent native type to IntPtr is void*, an untyped pointer.

So your class in C# should be:

[StructLayout(LayoutKind.Sequential)]
public class xyz
{
    IntPtr np;
    IntPtr foo;
}

To read the scalar value that np refers to call Marshal.ReadInt32. And to write it call Marshal.WriteInt32. But more likely, since this is a pointer, the pointer refers to an array. In which case you use the appropriate Marshal.Copy overload to read and write.

For the pointer to double, if the value is a scalar there is no method in Marshal to read or write the value. But again, it is surely an array in which case use Marshal.Copy to access the contents.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • You are confusing IntPtr with an array of pointers. The way to do this, I discovered, is: [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public IntPtr[] np;. You may find this link helpful:http://stackoverflow.com/questions/18647501/marshal-array-of-doubles-from-c-to-c-sharp – PaeneInsula Sep 05 '13 at 23:54
  • I'm not confused at all. Your ByValArray matches nothing in this question. – David Heffernan Sep 06 '13 at 06:11
  • Let's read my answer again. I stated that "An IntPtr is an integer that is the same width as a pointer." And that "The closest equivalent native type to IntPtr is void*, an untyped pointer." From that it is clear that my understanding of IntPtr is solid. – David Heffernan Sep 06 '13 at 06:19