Platform Invocation Services

 
Chapter 17 - COM Interoperability
bySimon Robinsonet al.
Wrox Press 2002
  

Weve talked about interoperability between COM components and .NET. While were on the subject of interoperability, lets talk about another kind: that which is between .NET code and functions available from unmanaged Win32 DLLs. The technology for achieving this is called Platform Invocation Services, or PInvoke for short.

As we mentioned at the start of the chapter, unmanaged code is not managed by the .NET runtime. When a .NET applications thread-of-execution enters a segment of unmanaged code, the .NET runtime no longer has control over what that code does, and is unable to enforce garbage collection or security rules on it. For this reason, applications that use unmanaged code must be endowed with a trust by the system administrator.

Platform Invocation Services allow .NET code to interoperate with code that is not only unsafe, but also authentically unmanaged.

Accessing Unmanaged Code

To use Platform Invocation Services to call an unmanaged, external function, we must declare the target function at the top of a C# file. Providing no implementation, this declaration gives the target functions name , lists its input arguments, and associates the function with the name of the DLL from which the function is available. This is done through the DllImport attribute of the System.Runtime.InteropServices namespace.

The following simple console application example uses the Windows API to create a message box:

   using System;     using System.Runtime.InteropServices;     namespace Wrox.ProCSharp.ComInterop.UnmanagedExample     {     class PInvokeExample     {     //Declare the external, unmanaged function.     [DllImport ("user32.dll")]     public static extern int MessageBoxA (int Modal,     string Message,     string Caption,     int Options);         //Program starts here.     public static void Main (string[] args)     {     //Invoke the unmanaged function using PInvoke.     MessageBoxA(0,"PInvoke worked!","PInvoke Example",0);     }     }     }   

When the code calls the unmanaged function, PInvoke loads the functions DLL into memory, locates the address of the function, and marshals the C# input arguments to types that the DLL function will understand. Then PInvoke activates the function, moving the applications thread-of-execution into the unmanaged DLL. As the example above shows, a call to an unmanaged function looks just like the call to an ordinary, managed one.

An important thing to note about the above code is the use of the extern keyword in the unmanaged functions declaration. This indicates that the function is defined externally, so we dont have to supply a definition within our code itself. Now, client .NET code can invoke the exported function by calling the managed declaration that we tagged with the [DllImport] attribute.

Although we chose to give the wrapper function the same name as the Windows API call to which it maps, we could give it a different name as well, as we do in the example below. Here, we change the name MessageBoxA to one that more accurately specifies how the API call will be used. We do this by using the EntryPoint parameter with the DllImport attribute to specify an alias name for the external function:

   [DllImport("user32.dll",EntryPoint="MessageBoxA")]     public static extern int ErrorMessage(int Modal,   string Message,                                       string Caption,                                       int Options); 

With an alias defined for the managed declaration, C# clients can invoke the exported function using this alias name, as shown below:

   ErrorMessage(0, "PInvoke worked with alias name!", "PInvoke Example",0);   

The Drawback to Pinvoke

As youve seen, its pretty easy to reference and invoke an unmanaged function from .NET code. Unfortunately, there is a potential drawback to using unmanaged code in this fashion.

Although Microsoft has consistently sidestepped the issue of platform interoperability, many people suspect that it is on the horizon for .NET. With platform interoperability in place, you could run a .NET program on any platform from Macintosh to Unix, provided that the platform was equipped with a .NET runtime. However, when you use PInvoke , you couple your .NET code to the Windows operating system.

When you consider using PInvoke , first check to see that the functionality you need isnt exposed somewhere by the .NET base classes; the most useful stuff is in there. If the .NET runtime were ever ported to a different platform, the .NET base classes would be ported, too, and your code would have a good chance of running correctly on the new platform with few (if any) changes.

  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net