title: Marshal C# class with reference members to C++
body: <p>We have a task to pass a class with a reference to another class from C# to C++. C# class looks like this:</p>
  
  <pre class="lang-cs prettyprint-override"><code>[StructLayout(LayoutKind.Sequential, Pack=1)]
  public class ImageInfo
  {
      public uint Width;
      public uint Height;
      public uint Stride;
  }
  
  [StructLayout(LayoutKind.Sequential, Pack=1)]
  internal class FrameInfo
  {
      public int FrameNumber;
      public double TimeStamp;
      public ImageInfo Image; // This is the problem
  }
  </code></pre>
  
  <p>C++ struct looks like this (pack is also 1):</p>
  
  <pre class="lang-cpp prettyprint-override"><code>struct FrameInfo
  {
  public:
  
      unsigned int    frameNumber;
      double          timeStamp;
      ImageInfo       *image;
  };
  
  struct ImageInfo
  {
  public:
  
      unsigned int     m_width;
      unsigned int     m_height;
      unsigned int     m_stride;
  };
  </code></pre>
  
  <p>We pass the C# class to C++ in such a way:</p>
  
  <pre class="lang-cs prettyprint-override"><code>[DllImport("ourLib.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
  public static extern int OnFrame(int pId, FrameInfo pFrame);
  </code></pre>
  
  <p>And accept it in C++:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>extern "C" __declspec(dllexport) int OnFrame(int pId, const FrameInfo *pFrame);
  </code></pre>
  
  <p>As a result in the <code>FrameInfo</code> struct we have not a reference but an embedded class. Memory layout looks like this:</p>
  
  <pre><code>0..3 bytes:   uint   frameNumber
  
  4..11 bytes:  double timeStamp
  
  12..15 bytes: uint   width
  
  16..19 bytes: uint height
  
  etc... 
  </code></pre>
  
  <p>instead of:</p>
  
  <pre><code>0..3 bytes:   uint   frameNumber
  
  4..11 bytes:  double timeStamp
  
  12..15 bytes: ImageInfo* image  // pointer to the image
  </code></pre>
  
  <p>Class embedding causes an additional data copying that makes us very upset. We tried to pass the reference as <code>IntPtr</code> with the help of <code>Marshal.StructureToPtr()</code> but MSDN says that</p>
  
  <blockquote>
    <p>"StructureToPtr copies the contents of structure to the pre-allocated block of memory"</p>
  </blockquote>
  
  <p>so that it also copies the data.</p>
  
  <p>Then we tried to use C-style pointers in C#:</p>
  
  <pre class="lang-cs prettyprint-override"><code>[StructLayout(LayoutKind.Sequential, Pack=1)]
  internal unsafe class FrameInfo
  {
      public int FrameNumber;
      public double TimeStamp;
      public ImageInfo *Image;
  }
  </code></pre>
  
  <p>Compiler says that "Cannot take the address of, get the size of, or declare a pointer to a managed type"</p>
  
  <p>OK. Then we tried a strange not-documented function <code>__makeref()</code> and then casting it to the IntPtr but it also has rather strange memory layout.</p>
  
  <p>So, is there any way to pass the reference just as usual reference?</p>