Because P/Invoke does a lot of extra stuff (pinning, blitting, error
C++ interop just pushes the parameters on the stack and calls the function.
Ok, some things still need to be converted or pinned, but with C++ interop
you can convert once and call a whole bunch of APIs, with P/Invoke EVERY
parameter passed by address gets pinned and unpinned on EVERY call, copied
and copied back, etc. Or C++ interop can avoid the pinning problem entirely
by creating POD structures on the native heap where they never move around.
Plus the C++/CLI compiler inherited a lot of very complicated optimization
logic that .NET hasn't duplicated yet.