NGWS SDK Documentation  

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Overview of Platform Invocation Services

Platform Invocation Services, abbreviated throughout this spec to “PInvoke”, allows managed code to call unmanaged functions that are implemented in a DLL. PInvoke takes care of finding and invoking the correct function, as well as marshaling its managed arguments to and from their unmanaged counterparts (integers, strings, arrays, structures, etc).

PInvoke was intended primarily to allow managed code to call existing, unmanaged code, typically written in C. A good example is the several thousand functions that comprise the Win32 API. [Whilst this was its original intent, PInvoke can be applied to other scenarios]

When PInvoke calls an unmanaged function, it locates the DLL where that function lives, loads that DLL into process memory, finds the function address in memory, pushes its arguments onto the stack (marshaling if required), enables pre-emptive garbage collection, and transfers control to the address for the unmanaged code.

Note: although it is possible to export methods of a class from a DLL, PInvoke does not support calling such methods. PInvoke only supports calling global functions exported from the DLL.PInvoke knows what to do from metadata, stored into the image file. This metadata, in turn, was generated by the compiler in response to extra information that the programmer writes into his source code, that describes the function and its arguments.

A similar process is used when NGWS runtime managed code inter-operates with existing COM code. Many of the steps are similar – locate the target methods, push arguments, marshaling if required, and transferring control. In fact, PInvoke and COM Interop share much of that marshaling code inside the NGWS runtime, so understanding one helps understand the other.

In the current release of the NGWS runtime, PInvoke is limited as follows: you can start executing managed code, and call unmanaged code. And from that unmanaged code, you can even return to managed code via a callback (see later). However, for the moment, you cannot start in unmanaged code and call managed code.

By a callback, we mean a pointer to managed code, that is passed as an argument to the unmanaged function. An example would be calling an unmanaged QuickSort function; one of its arguments is a pointer to a comparison function; if that comparison function is implemented as managed code, we call it a callback, for obvious reasons.

[There is one particular scenario, called “It Just Works” where you can start in unmanaged code, and call managed code. However, this is a special case that does not involve ‘classic’ PInvoke data marshaling. Such IJW scenarios are not discussed further in this document]