title: Using a C++ DLL in C# when signature includes BYTE**
body: <p>I am working on a C# project, and am wrapping a C++ DLL for use in the project.  I have captured this behaviour in a test project, with function calls renamed to protect the innocent.</p>
  
  <p>Everything seems fine, except for one type of function that I am having a hard time understanding.  The signature for that function in the DLL header is:</p>
  
  <pre><code>int32_t DoTheWork(BYTE **dest, BYTE *Src, int32_t szSrc);
  </code></pre>
  
  <p>My wrapper receives the Src byte array with no problem (easily tested since this is just a char string).  The return dest paramater is not quite so simple.</p>
  
  <p>I have tried different ways to pass the dest parameter from C# to the wrapped function, but when I receive it back, either the dest byte array in C# has a length of 1 (instead of the expected 32) bytes, or the return crashes.  The instance I have below is a crash.  I need to understand how to pass a byte array as reference, copy results into that byte array, and return it with the full complement of bytes without crashing.  I have spent more than a day on this looking online and making changes to code, but am still not getting it to work correctly.</p>
  
  <p>Also, would it be better for me to just take the pointer created in the C++ DLL all the way up into the C# calling function, instead of copying the values into the C# byte array in my C++ wrapper?  If so, how do I correctly go about cleaning up that memory inside of C#?</p>
  
  <p>I am using VS2010 on Win8.  Here's my code:</p>
  
  <p>** OriginalCPPClass.h for OriginalCPPDll.dll</p>
  
  <pre><code>class OriginalCPPClass {
  public:
      OriginalCPPDLLClass();
      virtual ~OriginalCPPDLLClass();
      int32_t DoTheWork(BYTE **dest, BYTE *Src, int32_t szSrc);
  };
  </code></pre>
  
  <p>** WrapperDLL.cpp (no accompanying .h file)</p>
  
  <pre><code>#include "CytoCrypto.h"
  
  extern "C"
  {
  
  #define WRAPPERCLASS_EXPORT __declspec(dllexport)
  
  WRAPPERCLASS_EXPORT OriginalCPPClass* Wrap_Create()
  {
      return new OriginalCPPClass();
  }
  
  WRAPPERCLASS_EXPORT void Wrap_Destroy(OriginalCPPClass* pObj)
  {
      delete pObj;
  }
  
  WRAPPERCLASS_EXPORT int32_t __cdecl Wrap_DoTheWork(OriginalCPPClass* pObj, BYTE **pDest, BYTE *pSrc, int32_t szSrc)
  {
      BYTE *result = NULL;
      int32_t sz = pObj-&gt;DoTheWork(&amp;result, pSrc, szSrc);
      *(result+sz) = '\0';
      if (sz &gt; 0)
      {
          memcpy(pDest, result, sz );
      }
      return (sz &gt;= 0) ? sz : 0;
  }
  
  }
  </code></pre>
  
  <p>** Program.cs</p>
  
  <pre><code>using System;
  using System.Text;
  using System.Runtime.InteropServices;
  
  
  namespace ConsoleApplication1
  {
      class Program
      {
          [DllImport("OriginalCPPDll.dll", CallingConvention = CallingConvention.Cdecl)]
          public static extern IntPtr Wrap_Create();
  
          [DllImport("OriginalCPPDll.dll", CallingConvention = CallingConvention.Cdecl)]
          public static extern void Wrap_Destroy(IntPtr pObj);
  
          [DllImport("OriginalCPPDll.dll", CallingConvention = CallingConvention.Cdecl)]
          public static extern Int32 Wrap_DoTheWork(IntPtr pObj, out IntPtr pDest, byte[] src, Int32 szSrc);
  
          static void Main(string[] args)
          {
              string src = "this is the source string";
              IntPtr pnt = Marshal.AllocHGlobal(1000);
              byte[] bytearray = new byte[1000];
              byte[] srcBytes = Encoding.ASCII.GetBytes(src);
              Int32 szSrc = srcBytes.Length;
  
              IntPtr obj = Wrap_Create();
              Int32 size = Wrap_DoTheWork(obj, out pnt, srcBytes, szSrc);
              Marshal.Copy(pnt, bytearray, 0, size);
              Wrap_Destroy(obj);
  
              Marshal.Copy(pnt, bytearray, 0, size);
          }
      }
  }
  </code></pre>
  
  <p>Error dialog says:</p>
  
  <p>An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll
  Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</p>