Reverse P/Invoke and exception

P/Invoke is managed code executing a native function pointer. And Reverse P/Invoke is native code executing a managed delegate as a function pointer, mostly as a callback.

When the native code executes the managed delegate function pointer, the call really calls into a CLR thunk. The thunk will do an AppDomain transition to the correct AppDomain, then invoke the delegate. If the managed delegate throws an unhandled exception in the callback, the exception will be raised as cross context exception at the base of the AppDomain transition, and will likely cause a Dr.Watson error report.

If we don’t want the managed exception to trigger Watson report, there are two things we could do.

1) have a top level try/catch block in the managed delegate and catch all exceptions. Yes we need some mechanism to convey the error information to the native code. We can either have the managed delegate return an HRESULT, or have it as one of the out parameter.

2) use ICLRRuntimeHost::ExecuteInAppDomain. CLR will catch any unhandled exception and convert it to an HRESULT to return to the caller.

Comments (3)

  1. Clinton Pierce says:

    "reverse p/invoke".  When did this show up?  A couple of years ago I remember looking around for how to do this (call from unmanaged to managed) any the only official way seemed to be using COM interfaces (*gag*).

    So that’s what we did.  When what we really wanted was "reverse p/invoke".  

    Now I know what to Google for…Thanks.

  2. Random Reader says:

    "Reverse P/Invoke" is what you get when you pass a managed delegate to unmanaged code (as a function pointer), and it’s been there since the beginning. It’s not a generic "get a CLR instance and call into it from the outside" kind of thing, which is probably what you needed COM for.

    When dealing with exceptions, you still want a COM interface just due to the HRESULT handling. Without that, exceptions will end up being tunneled through a CLR-specific exception code and bypass any useful handling you could do on the unmanaged side, which is the point of this blog post :)

    As a side note, this is the single clearest explanation for why ICLRRuntimeHost::ExecuteInAppDomain exists I’ve seen to date. The docs are rather opaque about what you’re supposed to do with it, and what exactly it expects to execute.

  3. Most people have encountered the need for interoperability between managed and unmanaged code. There