title: Proper way to export a marshaled struct
body: <p>I am writing a managed DLL that uses a 3rd party native DLL whose header contains:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>typedef struct {
     Bool isMounted;
     char *symbolicLink;
  } VolumeInfo;
  
  ErrorCode GetVolumeInfo(VolumeHandle handle, VolumeInfo **info);
  void FreeVolumeInfo(VolumeInfo *info);
  </code></pre>
  
  <p>I marshaled this as:</p>
  
  <pre class="lang-cs prettyprint-override"><code>[StructLayout(LayoutKind.Sequential]
  internal struct NativeVolumeInfo
  {
      public bool IsMounted;
      public IntPtr SymbolicLink;
  }
  
  static extern ErrorCode GetVolumeInfo(IntPtr volumeHandle, out IntPtr volumeInfoPointer);
  static extern void FreeVlumeInfo(IntPtr volumeInfoPointer);
  </code></pre>
  
  <p>The rationale is:<br>
  - <code>VolumeInfo.SymbolicLink</code> has to be an <code>IntPtr</code> instead of <code>string</code> because its size is dynamic and I don't know what the charset is. Besides, the native code <em>is supposed to not set it</em> if <code>isMounted</code> is <code>false</code>, but this is not always the case and I sometimes ended up with gibberish from the unmanaged memory.<br>
  - I need to get the pointer to <code>volumeInfoHandle</code> from native and then pass it back for freeing. So I cannot simply pass the managed struct as <code>out</code> on <code>GetVolumeInfo</code> and rely on the marshaller to fill it in for me.  </p>
  
  <p>My goal is to expose this volume information to the end users of my DLL. So I have this API class that uses the native methods behind the scenes and returns a more user-friendly struct:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public struct VolumeInfo
  {
    public bool IsMounted {get;set;}
    public string SymbolicLink {get;set;}
  }
  
  public class PublicApi
  {
    public VolumeInfo GetVolumeInfo(Volume volume)
    {
      IntPtr volumeInfoPointer;
      var errorCode = NativeMethods.GetVolumeInfo(volume.Handle, out volumeInfoPointer);
      if (errorCode == 0)
      {
        var nativeVolumeInfo = (NativeVolumeInfo)Marshal.PtrToStructure(volumeInfoPointer, typeof(NativeVolumeInfo));
        try
        {
          var volumeInfo = new VolumeInfo { IsMounted = nativeVolumeInfo.IsMounted };
          if (volumeInfo.IsMounted)
          {
            volumeInfo.SymbolicLink = Marshal.PtrToStringAnsi(nativeVolumeInfo.SymbolicLink);
          }
          return volumeInfo;
        }
        finally
        {
          NativeMethods.FreeVolumeInfo(volumeInfoPointer);
        }           
      }
      throw new InvalidOperationException("Didn't work");
    }
  }
  </code></pre>
  
  <p>At this point I am worried that for every native struct that I need to marshal manually I have to write 2 managed structs: one for marshaling and another one to export to end-users.  </p>
  
  <p>Is there any way to make this easier?</p>