title: C# Marshalling bool
body: <p><strong>Scenario</strong></p>
  
  <p>This should be an easy task, but for some reason I can't get it going as intended. I have to marshal a basic C++ <code>struct</code> during a reversed-P/Invoke call (unmanaged calling managed code).</p>
  
  <p>The issue only arises when using <code>bool</code> within the struct, so I just trim the C++ side down to:</p>
  
  <pre><code>struct Foo {
      bool b;
  };
  </code></pre>
  
  <p>Since .NET marshals booleans as 4-byte fields by default, I marshal the native boolean explicitly as a 1 byte-length field:</p>
  
  <pre><code>public struct Foo {
      [MarshalAs(UnmanagedType.I1)] public bool b;
  }
  </code></pre>
  
  <p>When I call an exported managed static method with the following signature and body:</p>
  
  <pre><code>public static void Bar(Foo foo) {
      Console.WriteLine("{0}", foo.b);
  }
  </code></pre>
  
  <p>I get the correct boolean alpha-representation printed. If I extend the structure with more fields, the alignment is correct and the data is not corrupt after marshalling.</p>
  
  <p><strong>Problem</strong></p>
  
  <p>For some reason, if I do not pass this marshalled <code>struct</code> as an argument but rather as a return type by value:</p>
  
  <pre><code>public static Foo Bar() {
      var foo = new Foo { b = true };
      return foo;
  }
  </code></pre>
  
  <p>The application crashes with the following error message:</p>
  
  <p><a href="https://i.stack.imgur.com/u6knw.png" rel="noreferrer"><img src="https://i.stack.imgur.com/u6knw.png" alt="enter image description here"></a></p>
  
  <p>If I change the managed structure to hold a <code>byte</code> instead of a <code>bool</code></p>
  
  <pre><code>public struct Foo {
      [MarshalAs(UnmanagedType.I1)] public byte b;
  }
  
  public static Foo Bar() {
      var foo = new Foo { b = 1 };
      return foo;
  }
  </code></pre>
  
  <p>the return value is marshalled properly without an error to an unmanaged bool.</p>
  
  <p>I don't unterstand two things here:</p>
  
  <ol>
  <li>Why does a paramter marshalled with <code>bool</code> as described above work, but as a return value give an error?</li>
  <li>Why does a <code>byte</code> marshalled as <code>UnmanagedType.I1</code> work for returns, but a <code>bool</code> also marshalled with <code>UnmanagedType.I1</code> does not?</li>
  </ol>
  
  <p>I hope my description makes sense -- if not, please let me know so I can change the wording.</p>
  
  <p><strong>EDIT:</strong>
  My current workaround is a managed struct like:</p>
  
  <pre><code>public struct Foo {
      private byte b;
      public bool B {
          get { return b != 0; }
          set { b = value ? (byte)1 : (byte)0; }
  }
  </code></pre>
  
  <p>which honestly, I find quite ridiculous...</p>
  
  <p><strong>EDIT2:</strong> Here is an almost-MCVE. The managed assembly has been recompiled with proper symbol exports (using <code>.export</code> and <code>.vtentry</code> attributes in IL code), but there <em>should</em> be no difference to C++/CLI calls. So this code is not working "as-is" without doing the exports manually:</p>
  
  <p><strong>C++ (native.dll):</strong></p>
  
  <pre><code>#include &lt;Windows.h&gt;
  
  struct Foo {
      bool b;
  };
  
  typedef void (__stdcall *Pt2PassFoo)(Foo foo);
  typedef Foo (__stdcall *Pt2GetFoo)(void);
  
  int main(int argc, char** argv) {
      HMODULE mod = LoadLibraryA("managed.dll");
      Pt2PassFoo passFoo = (Pt2PassFoo)GetProcAddress(mod, "PassFoo");
      Pt2GetFoo getFoo = (Pt2GetFoo)GetProcAddress(mod, "GetFoo");
  
      // Try to pass foo (THIS WORKS)
      Foo f1;
      f1.b = true;
      passFoo(f1);
  
      // Try to get foo (THIS FAILS WITH ERROR ABOVE)
      // Note that the managed method is indeed called; the error
      // occurs upon return. If 'b' is not a 'bool' but an 'int'
      // it also works, so there must be something wrong with it
      // being 'bool'.
      Foo f2 = getFoo();
  
      return 0;
  }
  </code></pre>
  
  <p><strong>C# (managed.dll):</strong></p>
  
  <pre><code>using System;
  using System.Runtime.InteropServices;
  
  public struct Foo {
      [MarshalAs(UnmanagedType.I1)] public bool b;
      // When changing the above line to this, everything works fine!
      // public byte b;
  }
  
  /*
      .vtfixup [1] int32 fromunmanaged at VT_01
      .vtfixup [1] int32 fromunmanaged at VT_02
      .data VT_01 = int32(0)
      .data VT_02 = int32(0)
  */
  
  public static class ExportedFunctions {
      public static void PassFoo(Foo foo) {
           /*
               .vtentry 1:1
               .export [1] as PassFoo
           */               
  
           // This prints the correct value, and the
           // method returns without error.
           Console.WriteLine(foo.b);
      }
  
      public static Foo GetFoo() {
           /*
               .vtentry 2:1
               .export [2] as GetFoo
           */
  
           // The application crashes with the shown error
           // message upon return.
           var foo = new Foo { b = true; }
           return foo;
      }
  }
  </code></pre>