title: C# C++ Interop callback
body: <p>I have recently been tinkering around with C# to C++ interop, in particularly setting up a callback function which is called from the C++ DLL.</p>
  
  <pre><code>namespace TomCSharpDLLImport
  {
      class Program
      {
          public delegate void TomDelegate(int a, int b);
  
          [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)]
          public static extern void GetData();
  
          [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)]
          public static extern void SetCallback(TomDelegate aCallback);
  
          static void Main(string[] args)
          {
              TomDelegate lTD = new TomDelegate(Program.TomCallback);
  
              SetCallback(lTD); //Sets up the callback
  
              int thread = Thread.CurrentThread.ManagedThreadId;
  
              GetData(); //This calls the callback in unmanaged code
  
              while (true) ;
          }
  
          //Callback function which is called from the unmanaged code
          public static void TomCallback(int a, int b)
          {
              Console.WriteLine("A: {0} B: {1}", a, b);
              int thread = Thread.CurrentThread.ManagedThreadId;
          }
      }
  }
  </code></pre>
  
  <p>The question I have is that, when the program control comes into the TomCallback function, I was expecting it to then hit the while(true) loop in Main. However instead the program just exits. I can't quite get my head round the behaviour, part of me imagines this is as expected but part of me would have expected it to continue on in main.</p>
  
  <p>What I was expecting...</p>
  
  <ol>
  <li>The GetData() function is called</li>
  <li>The GetData function calls the callback</li>
  <li>The callback function returns back to GetData</li>
  <li>GetData returns back to main()</li>
  </ol>
  
  <p>However this is not quite right.</p>
  
  <p>Would someone be kind enough to explain what happens.</p>
  
  <p>In order to save space I haven't posted the unmanaged code, however if it is needed i'm happy to post</p>
  
  <p><strong>Edit:</strong>
  I turned on Unmanaged debugging (totally forgot to do this) and now I see the crash..</p>
  
  <blockquote>
    <p>Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.</p>
  </blockquote>
  
  <p>Native code as this is where crash is</p>
  
  <pre><code>#include "stdafx.h"
  typedef void (*callback_function)(int, int);
  
  extern "C" __declspec(dllexport) void SetCallback(callback_function aCallback);
  extern "C" __declspec(dllexport) void GetData();
  
  callback_function gCBF;
  
  __declspec(dllexport) void SetCallback(callback_function aCallback)
  {
      gCBF = aCallback;
  }
  
  __declspec(dllexport) void GetData()
  {
      gCBF(1, 2);
  }
  </code></pre>