21.10 Calling Native Unmanaged Code Using PInvoke

 < Day Day Up > 

21.10 Calling Native Unmanaged Code Using PInvoke

You want to call some function that is implemented as unmanaged code in a dynamic link library (DLL), such as a Windows API function.


Technique

To call unmanaged code using the PInvoke mechanism, you follow these steps:

  1. Identify the unmanaged DLLs that contain the unmanaged functions you want to call.

  2. Provide static extern definitions for wrapper functions in the C# source code, marking the definitions with the [DllImport] attribute and selecting appropriate data types for the parameters and any return values, which are marshaled correctly to the types expected by the unmanaged function.

For example, suppose you are doing some graphics processing and you need to create a memory device context compatible with the screen. You normally use the Windows API function CreateCompatibleDC() , defined in the file gdi32.dll . This function has the following unmanaged C++ signature:

 
 HDC CreateCompatibleDC(HDC hdc); 

Here, HDC is simply a typedef for a 32-bit integer used as a handle. Good managed programming practice normally suggests we use a System.IntPtr instance to represent 32-bit integers that are intended to be used as Windows handles. Hence, a suitable managed wrapper definition follows :

 
 class ClassThatDoesGraphicsProcessing {         [DllImport("gdi32.dll")]         static extern IntPtr CreateCompatibleDC(IntPtr hdc); 

You can now call the method as if it were a normal static class method. The following code shows this move and also includes the supporting (managed) code to create and release the screen device context to be passed to CreateCompatibleDC() :

 
 // get a screen device context // we assume this code is in a Windows.Forms.Control-derived class, hence // we can call Control.CreateGraphics(). Graphics g = this.CreateGraphics(); IntPtr hdcScreen = g.GetHdc(); // get a memory device context IntPtr hdcMemory = CreateCompatibleDC(hdcScreen); // other code to use the device context g.ReleaseHdc(hdcScreen); 

Comments

In general, the hardest part of using PInvoke to call an unmanaged function is the choice of parameter type. Using an inappropriate type can decrease performance, but in general, you will find that the type you intuitively expect is often the most appropriate type. For example, if an unmanaged function expects a C-style string, then pass in String . If it expects a 16-bit integer, then pass in short or ushort , depending on how the integer is best interpreted in the managed code. For a 32-bit integer, pass in int , uint , or IntPtr , again depending on which one represents the most appropriate usage of the value. Notice that in many cases there is no one correct type: It is a question of what the most appropriate type is depending on the purpose of the parameter. In these cases, choosing an inappropriate type will not cause any bugs but will make your code harder to understand.

Although the security risks are similar for unsafe code and unmanaged code, the two types of code are conceptually very different. There is no need to use the unsafe C# statement or /unsafe compiler option to invoke unmanaged code. Your code will, however, need the unmanaged code security permission to execute.

The PInvoke wrapper functions are always declared as static members of a class. This step is not actually a requirement of the CLR, which simply requires a non-instance function, but is necessary because C# does not support global functions.

 < Day Day Up > 


Microsoft Visual C# .Net 2003
Microsoft Visual C *. NET 2003 development skills Daquan
ISBN: 7508427505
EAN: 2147483647
Year: 2003
Pages: 440

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