Search code examples
c#.netpinvokeunmanagedmanaged

What exactly happens during a "managed-to-native transition"?


I understand that the CLR needs to do marshaling in some cases, but let's say I have:

using System.Runtime.InteropServices;
using System.Security;

[SuppressUnmanagedCodeSecurity]
static class Program
{
    [DllImport("kernel32.dll", SetLastError = false)]
    static extern int GetVersion();

    static void Main()
    {
        for (; ; )
            GetVersion();
    }
}

When I break into this program with a debugger, I always see:

Given that there is no marshaling that needs to be done (right?), could someone please explain what's actually happening in this "managed-to-native transition", and why it is necessary?


Solution

  • First the call stack needs to be set up so that a STDCALL can happen. This is the calling convention for Win32.

    Next the runtime will push a so called execution frame. There are many different types of frames: security asserts, GC protected regions, native code calls, ...

    The runtime uses such a frame to track that currently native code is running. This has implications for a potentially concurrent garbage collection and probably other stuff. It also helps the debugger.

    So not a lot is happening here actually. It is a pretty slim code path.