title: P/Invoke C# struct with strings to C void*
body: <p>I'm having a problem creating a C# P/invoke wrapper around a third party C library. In particular, the library has a method with the signature</p>
  
  <pre><code>int command(SomeHandle *handle, int commandNum, void *data, int datasize);</code></pre>
  
  <p>It is a wildcard method that does different things depending on commandNum. data can be a pointer to anything, like a single integer, or a char[], or a struct of some kind (my problem).</p>
  
  <p>I have declared the wrapper as follows:</p>
  
  <pre><code>
  [DllImport("LIBRARY.DLL", EntryPoint = "command")]
  public static extern int Command(IntPtr Handle, int CommandNum, [In, Out] IntPtr Data, int DataSize);
  </code></pre>
  
  <p>Now, when i call it with an opcode to fill a byte[] it works:</p>
  
  <pre><code>
  //WORKS, Buffer contains "library 1.0" after the call
  const int BUFFER_SIZE = 128;
  byte[] Buffer = new byte[BUFFER_SIZE];
  int BytesWritten = 0;
  GCHandle BufferHandle = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
  try
  {
      BytesWritten = Command(MyHandle, GET_VERSION, BufferHandle.AddrOfPinnedObject(), BUFFER_SIZE);
  }
  finally
  {
      BufferHandle.Free();
  }
  </code></pre>
  
  <p>However, when I try the same with a simple struct, I cannot make it work, no matter what I try. the struct looks like this:</p>
  
  <pre><code>
  public struct FormatInfoType
  {
      public int Format;
      public IntPtr Name; //const char* 
      public IntPtr Extension; //const char* 
  }
  </code></pre>
  
  <p>Here I am supposed to fill "Format" with an int (say, 1) and then the call to "command(...)" is meant to give me back the name and extension fields </p>
  
  <p>If I pass this struct, the code compiles and runs correctly, but the values in the struct are never modified. If I change the IntPtr's to Strings or StringBuilders (and I've tried a myriad of MarshalAs attributes), then I cannot get the IntPtr to the struct because the it becomes non-blittable and the GCHandle line throws an exception.</p>
  
  <p>Any help on this would be greatly appreciated.</p>
  
  <p><b>EDIT:</b></p>
  
  <p>I've tried many ways to call command() with the structure, but currently it looks like this:</p>
  
  <pre><code>
  FormatInfoType f = new FormatInfoType();
  f.Format = 1;
  f.Name = IntPtr.Zero;
  f.Extension = IntPtr.Zero;
  
  GCHandle fHandle = GCHandle.Alloc(f, GCHandleType.Pinned);
  try
  {
      Command(MyHandle, GET_FORMAT_INFO, fHandle.AddrOfPinnedObject(), Marshal.SizeOf(f));
  }
  finally
  {
  fHandle.Free();
  }
  </code></pre>