title: C# callback from C++ gives access violation
body: <p>EDIT(Thank you ildjarn!):
  Solved by changing delegate(and Callback function signature to match) to</p>
  
  <pre><code>[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  public delegate void InstallStatusDel([MarshalAs(UnmanagedType.LPStr)]string Mesg, int Status);
  </code></pre>
  
  <p>Original post:</p>
  
  <p>I have a problem with a .net application written in C# that calls functions in a C dll. I've looked at other threads with similar questions but I must be missing something different. When I debug this in C# I am able to hit a breakpoint in InstallStatusCallback but when execution exits InstallStatusCallback there is an AccessViolationException. I've tried debugging with C and the access violation occurs before execution returns back from the callback. Thank you for any input.</p>
  
  <p>Project settings in C dll are set to use __cdecl by default. In C DLL land the following code is in place:</p>
  
  <pre><code>typedef void (__cdecl *StatusCallback)(const char* Mesg, int Status);
  __declspec(dllexport) int Install(void* thing1, void* thing2, void* thing3, StatusCallback Func);
  
  
  int Install(void* thing1, void* thing2, void* thing3, StatusCallback Func)
  {
      Func("msg", 3);
      return 0;
  }
  </code></pre>
  
  <p>In C# I have:</p>
  
  <pre><code>public partial class InstallerStatus : Form
  {
      [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
      public delegate void InstallStatusDel(StringBuilder Mesg, int Status);
  
      public static extern int Install(IntPtr thing1, IntPtr thing2, IntPtr thing3, InstallStatusDel Func);
      [DllImport("myDll.dll", CallingConvention = CallingConvention.Cdecl)]
  
      private IntPtr mThing1;
      private IntPtr mThing2;
      private InstallStatusDel mInstallStatusFunc;
      private BackgroundWorker mInstallWorker;
  
      public InstallerStatus(IntPtr pThing1, IntPtr pThing2)
      {
          InitializeComponent();
  
          mThing1 = pThing1;
          mThing2 = pThing2;
          mInstallStatusFunc = InstallStatusCallback;
  
          mProgressBar.Minimum = 0;
          mProgressBar.Maximum = 100;
          mProgressBar.Value = 0;
  
          mInstallWorker = new BackgroundWorker();
          mInstallWorker.DoWork += new DoWorkEventHandler(InstallWork);
          mInstallWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(InstallWork_Completed);
      }
  
      private void InstallWork(object sender, DoWorkEventArgs e)
      {
          Install(mThing1, mThing2, IntPtr.Zero, mInstallStatusFunc);
      }
  
      private void InstallWork_Completed(object sender, RunWorkerCompletedEventArgs e)
      {
          Close();
      }
  
      private void InstallStatusCallback(StringBuilder PartName, int Status)
      {
      }
  
      private void InstallLoad_Shown(object sender, EventArgs e)
      {
          mInstallWorker.RunWorkerAsync();
      }
  }
  </code></pre>