Team LiB
Previous Section Next Section

Using Platform Invoke to Call Native DLL Functions

To consume exported DLL functions from managed code, follow these steps:

  1. Obtain the function names and signatures for the desired native code.

  2. Create a class that will be used to wrap calls to the functions that you are calling. A good way to organize these is to have a separate class for every native DLL that you will be calling.

  3. Prototype the code. In C#, use DllImportAttribute to identify the DLL and function. Mark the method with the static and extern modifiers. For example, for an exported function defined as follows:

    extern "C" _declspec(dllexport) int __stdcall MyTest(int MyInt)
    
  4. The following is valid:

    using System.Runtime.InteropServices;
    DllImport("Test.dll")]
    public static extern int MyTest(int MyInt);
    
  5. Call the method of the wrapped class you created in step 2. This will result in the native function being called in whatever executable it is placed.

Arrays are marshaled by value unless specifically passed by reference. This behavior can be controlled using the [In, Out] attributes. The following examples demonstrate using platform invoke (PInvoke) to call native DLL functions.

Code Example: Using PInvoke to Call Native DLL Functions
Start example

using System;
using System.Runtime.InteropServices;

namespace Client.Chapter_10___COM_and_.NET_Interoperability
{
          public class Win32
          {
                 //The DllImport statement allows you to call exported functions
                  [DllImport("user32.dll", CharSet = CharSet.Auto)]
          public static extern int
               MessageBox(int hWnd, String text, String caption, uint type);
          }
          class Class1
          {
                [STAThread]
                static void Main(string[] args)
                {
                      //Calls an exported function
                       Win32.MessageBox(0, "Hello World", "MyBox", 1);
                }
          }
}
End example
Code Example: Call Native Functions: Array Parameter By Value
Start example

void ArrayOfInts(int* pArray, int psize);

using System;
using System.Runtime.InteropServices;

namespace Chapter10
{
     public class PassingArrayByValue
     {
         [DllImport( "My.dll" )]
         public static extern void ArrayOfInts(
                 [In, Out] int[] array, int size );

         public static void Main()
         {
             int[] array1 = new int[10];
             for( int i = 0; i < array1.Length; i++ )
             {
                array1[ i ] = i;
             }
             PassingArrayByValue.ArrayOfInts(array1,
                                    array1.Length);
         }
     }
}
End example
Code Example: Call Native Functions: Array Parameter By Reference
Start example

void RefArrayOfInts(int** ppArray, int* pSize);

using System;
using System.Runtime.InteropServices;

namespace Chapter10
{

      public class PassingArrayByRef
      {
          [DllImport( "My.dll" )]
          public static extern void RefArrayOfInts(
               ref IntPtr array, ref int size );
          public static void Main()
          {
               int[] array2 = new int[ 10 ];
               int size = array2.Length;
               for( int i = 0; i < array2.Length; i++ )
               {
                   array2[ i ] = i;
               }
               IntPtr buffer = Marshal.AllocCoTaskMem(
                       Marshal.SizeOf( size ) * array2.Length );
               Marshal.Copy( array2, 0, buffer, array2.Length );

               PassingArrayByRef.RefArrayOfInts(
                       ref buffer, ref size );
               if( size > 0 )
               {
                    int[] arrayRes = new int[ size ];
                    Marshal.Copy( buffer, arrayRes, 0, size );
                    Marshal.FreeCoTaskMem( buffer );
               }
          }
     }
}
End example
Code Example: Call Native Functions: Multidimensional Arrays
Start example

void MultiOfInts(int pMatrix[][COL_DIM], int row);

using System;
using System.Runtime.InteropServices;

namespace Chapter10
{

      public class PassingMultiOfInts
      {
           [DllImport( "My.dll" )]
           public static extern void MultiOfInts(
                          [In, Out] int[,] pMulti,
                          int row );
           public static void Main()
           {

                const int DIM = 10;
                int[,] multi = new int[ DIM, DIM ];


                for( int i = 0; i < DIM; i++ )
                {
                    for( int j = 0; j < DIM; j++ )
                    {
                       multi[ i, j ] = j;
                    }
                }
                PassingMultiOfInts.MultiOfInts( multi, DIM );
           }
      }
}
End example
Code Example: Call Native Functions: String Arrays
Start example

void ArrayofStrings(char** ppStrings, int size);


using System;
using System.Runtime.InteropServices;

namespace Chapter10
{


      public class PassingArrayOfStrings
      {

           [DllImport( "My.dll" )]
           public static extern void ArrayOfStrings(
               [In, Out] String[] stringArray, int size );
           public static void Main()
           {
               string[] strArray = { "Jan", "Feb", "Mar", "Apr","May" };
               PassingArrayOfStrings.ArrayOfStrings(
               strArray, strArray.Length );
           }
      }
}
End example
Code Example: Call Native Functions: Array of Struct1
Start example

void ArrayOfStructs(MyStruct* pStruct, int size);

typedef struct _MyStruct
{
   int x;
   int y;
} MYStruct;



using System;
using System.Runtime.InteropServices;

namespace Chapter10
{
      [ StructLayout( LayoutKind.Sequential )]
      public struct MyStruct
      {
          public int x;
          public int y;
          public MyStruct( int x, int y )
          {
             this.x = x;
             this.y = y;
          }
      }


      public class PassingArrayOfStructs
      {
          [DllImport( "My.dll" )]
          public static extern void ArrayOfStructs(
              [In, Out] MyStruct[] structArray, int size );

          public static void Main()
          {

             MyStruct[] points = { new MyStruct(1,1),
             new MyStruct(2,2), new MyStruct(3,3) };
             PassingArrayOfStructs.ArrayOfStructs(
             points, points.Length );
          }
      }
}
End example
Code Example: Call Native Functions: Array of Struct2
Start example

Void ArrayOfStructs2(MyName* pStruct, int size);


typedef struct _MYName
{
   char* first;
   char* last;
} MYName;


using System;
using System.Runtime.InteropServices;

namespace Chapter10
{
     [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
     public struct MyName
     {
         public String first;
         public String last;
         public MyName( String first, String last )
         {
            this.first = first;
            this.last = last;
         }
     }

     public class PassingArrayStructs2
     {
         [DllImport( "My.dll" )]
         public static extern void ArrayOfStructs2(
             [In, Out] MyName[] nameArray, int size );


         public static void Main()
         {


            MyName[] MyList = { new MyName( "John", "Doe" ),
                                new MyName( "Jane", "Doe" ),
                                new MyName( "Jim", "Doe" )};

            PassingArrayStructs2.ArrayOfStructs2(
                  MyList, MyList.Length );
         }
    }
}
End example

Team LiB
Previous Section Next Section