title: Calling C++ dll function from C#: Of structs, strings and wchar_t arrays
body: <p>Here's a simple problem I need to solve, but it makes me feel my hair turning gray as all my attempts are returning me the same error:</p>
  
  <p>"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."</p>
  
  <p>I have a sample app written in C++ which makes a call to the dll. Here is the relevant code:</p>
  
  <pre><code>    //function I need to call
  bool convertHKID_Name(char *code,RECO_DATA *o_data);    //hkid 
  
  //struct definition
  struct RECO_DATA{
      wchar_t FirstName[200];
      wchar_t Surname[200];
  };
  
  //how it is used in C++ code
  CString code;
  RECO_DATA data;
  GetDlgItemText(IDC_CODE,code);
  char _code[200];
  WideCharToMultiByte(CP_UTF8, 0, code, -1, (char *)_code, 200, NULL, NULL);
  ocr-&gt;convertHKID_Name(_code,&amp;data)
  </code></pre>
  
  <p>Now when I debug the C++ code, it does the proper thing - writes some Unicode data into the data struct.</p>
  
  <p>Here is my attempt to do the same in C#</p>
  
  <pre><code>    //my C# wrapper class
  public class cnOCRsdk
  {
      [StructLayout(LayoutKind.Sequential, Size=400, CharSet=CharSet.Unicode), Serializable]
      public struct RECO_DATA
      {
          [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 200)]
          public string FirstName;
          [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 200)]
          public string Surname;
      };
  
      [DllImport(@"cnOCRsdk.dll", CharSet=CharSet.Auto, EntryPoint = "?convertHKID_Name@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z")]
      public static extern bool convertHKID_Name(ref string num, ref RECO_DATA o_data);
  
      [DllImport("Kernel32.dll")]
      public static extern int WideCharToMultiByte(uint CodePage, uint dwFlags,
          [In, MarshalAs(UnmanagedType.LPWStr)]string lpWideCharStr,
          int cchWideChar,
          [Out, MarshalAs(UnmanagedType.LPStr)]StringBuilder lpMultiByteStr,
          int cbMultiByte,
          IntPtr lpDefaultChar, // Defined as IntPtr because in most cases is better to pass
          IntPtr lpUsedDefaultChar // NULL
          );
  }
  
  //my attempt to call the function from the dll
  cnOCRsdk.RECO_DATA recoData = new cnOCRsdk.RECO_DATA();
  string num = "262125355174";
  StringBuilder sb = new StringBuilder(200, 200);
  cnOCRsdk.WideCharToMultiByte(65001, 0, num, -1, sb, 200, IntPtr.Zero, IntPtr.Zero);
  string sbTostring = sb.ToString();
  //the next line generates the 'Attempted to read or write protected memory' error
  bool res = cnOCRsdk.convertHKID_Name(ref sbTostring, out recoData);
  </code></pre>
  
  <p>My guess is that I'm not marshaling the RECO_DATA structure properly, because it is this struct that gets written to by the convertHKID_Name function. But how should I fix it?</p>