title: Best way to call Managed .NET code from Unmanaged code
body: <p>I'm trying to find the best performing method of calling into Managed .NET code from Unmanaged C++ code.  I have found information on Hosting .NET within my C++ application and I'm able to create a pRuntimeHost and start it without a problem.</p>
  
  <p>The ExecuteInDefaultAppDomain seems very limited since I really want to send it a few parameters and have it return a structure of information.  The most obvious alternative is to use COM methods but the current C# code isn't really setup as interfaces with methods.</p>
  
  <p>Either way I want to return integers, strings (char *)s, doubles and other core C++ types.  There is too much code on both sides to convert the C++ to C# and using Managed C++ isn't an acceptable solution, since the other groups using this C++ code don't want to start using Managed code for performance reasons.</p>
  
  <p>The goal is modify the existing C++ and C# code as little as possible but still use methods within the C# code at specific points within the C++ without majorly affecting the speed of the C++ code.</p>
  
  <p>Based on code found on the Internet the startup and shutdown sequence to host .NET is:</p>
  
  <pre><code>#include "stdafx.h"
  #include &lt;metahost.h&gt;
  
  #pragma comment(lib, "mscoree.lib")
  
  int _tmain(int argc, _TCHAR* argv[])
  {
      ICLRMetaHost       *pMetaHost       = NULL;
      ICLRMetaHostPolicy *pMetaHostPolicy = NULL;
      ICLRDebugging      *pCLRDebugging   = NULL;
  
      HRESULT hr;
      hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&amp;pMetaHost);
      hr = CLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, (LPVOID*)&amp;pMetaHostPolicy);
      hr = CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (LPVOID*)&amp;pCLRDebugging);
  
      DWORD dwVersion = 0;
      DWORD dwImageVersion = 0;
      ICLRRuntimeInfo *pRuntimeInfo;
      hr = pMetaHost-&gt;GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID *)&amp;pRuntimeInfo);
  
      ICLRRuntimeHost * pRuntimeHost = NULL;
      hr = pRuntimeInfo-&gt;GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&amp;pRuntimeHost);
  
      hr = pRuntimeHost-&gt;Start();
  
      DWORD dwRetCode = 0;
      //hr = pRuntimeHost-&gt;ExecuteInDefaultAppDomain(argv[1], L"MyNamespace.MyClass", L"Message", L"Hello World!", &amp;dwRetCode);
  
      // Stop the CLR runtime and shutdown cleanly.
      hr = pRuntimeHost-&gt;Stop();
      hr = pRuntimeHost-&gt;Release();
      hr = pRuntimeInfo-&gt;Release();
      hr = pCLRDebugging-&gt;Release();
      hr = pMetaHostPolicy-&gt;Release();
      hr = pMetaHost-&gt;Release();
  
      return 0;
  }
  </code></pre>