title: Marshaling a SAFEARRAY of VARIANTs that are BYTEs to C#
body: <p>I create a <code>SAFEARRAY</code> storing <code>VARIANT</code>s that are <code>BYTE</code>s in C++.</p>
  
  <p>When this structure is marshaled to C#, a weird thing happens.</p>
  
  <p>If I print the content of this structure in C# to a WinForms <code>ListBox</code>, e.g.:</p>
  
  <pre><code>byte data[]
  TestSafeArray(out data);
  
  lstOutput.Items.Clear();    
  foreach (byte x in data)
  {
      lstOutput.Items.Add(x); // Strange numbers
  }
  </code></pre>
  
  <p>I get some numbers that seem unrelated to the original ones. Moreover, each time I run the C# client for a new test, I get a different set of numbers.</p>
  
  <p>Note that if I inspect the content of that <code>data</code> array with the Visual Studio debugger, I get the <em>correct</em> numbers, as the following screenshot shows:</p>
  
  <p><a href="https://i.stack.imgur.com/zOivu.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/zOivu.png" alt="VS debugger shows the correct numbers"></a></p>
  
  <p>However, if I <strong><code>CopyTo</code></strong> the marshaled <code>data</code> array to a new one, I get the <strong>correct numbers</strong>:</p>
  
  <pre><code>        byte[] data;
          TestSafeArray(out data);
  
          // Copy to a new byte array
          byte[] byteData = new byte[data.Length];
          data.CopyTo(byteData, 0);
  
          lstOutput.Items.Clear();
          foreach (byte x in byteData)
          {               
              lstOutput.Items.Add(x); // ** WORKS! **
          }
  </code></pre>
  
  <hr>
  
  <p>This is the C++ repro code I use to build the <code>SAFEARRAY</code> (this function is exported from a native DLL):</p>
  
  <pre><code>extern "C" HRESULT __stdcall TestSafeArray(/* [out] */ SAFEARRAY** ppsa)
  {
      HRESULT hr = S_OK;
      try 
      {
          const std::vector&lt;BYTE&gt; v{ 11, 22, 33, 44 };
  
          const int count = static_cast&lt;int&gt;(v.size());
          CComSafeArray&lt;VARIANT&gt; sa(count);
  
          for (int i = 0; i &lt; count; i++)
          {
              CComVariant var(v[i]);
  
              hr = sa.SetAt(i, var);
              if (FAILED(hr))
              {
                  return hr;
              }
          }
  
          *ppsa = sa.Detach();
      } 
      catch (const CAtlException&amp; e)
      {
          hr = e;
      }
  
      return hr;
  }
  </code></pre>
  
  <p>And this is the C# P/Invoke I used:</p>
  
  <pre><code>[DllImport("NativeDll.dll", PreserveSig = false)]
  private static extern void TestSafeArray(
      [Out, MarshalAs(UnmanagedType.SafeArray, 
                      SafeArraySubType = VarEnum.VT_VARIANT)]
      out byte[] result);
  </code></pre>
  
  <p>Note that if in C++ I create a <code>SAFEARRAY</code> storing <code>BYTE</code>s <em>directly</em> (instead of a <code>SAFEARRAY(VARIANT)</code>), I get the correct values immediately in C#, without the intermediate <code>CopyTo</code> operation.</p>