This example shows you how to use the DllImport attribute to create a message box by calling MessageBoxA from user32.dll. To examine the functions contained insystem component, use the dumpbin.exe tool that ships with the Microsoft Windows SDK:dumbin.exe user32.dll /all > user.txt
Example
/***** File: example.cs *****/
using System;
using System.Runtime.InteropServices;
// import the namespaceclass PlatformInvokeTest
// declare the class {[DllImport("user32.dll")]
//the Dllmport attribute public static extern int MessageBoxA(
// methods int h, string m, string c, int type);public static int Main()
// entry point {return MessageBoxA(0, "This is a Windows object!", "My MessageBox", 0);
// end of method}
// end of class}
/****************************************************************/
To compile:
c:\%windir%\Microsoft.NET\Framework\v2.0.50727>csc.exe example.cs
A Closer Look at Platform Invoke
There are two ways that C# code can directly call unmanaged code:
- Directly call a function exported from a DLL.
- Call an interface method on a COM object.
For both techniques, you must provide the C# compiler with a declaration of the unmanaged function, and you may also need to provide the C# compiler with a description of how to marshal the parameters andreturn value to and from the unmanaged code.
This section tutorial consists of the following topics:
- Calling a DLL Export Directly from C#.
- Default Marshaling and Specifying Custom Marshaling for Parameters to Unmanaged Methods
The sction includes the following examples:
- Example 1 Using DllImport
- Example 2 Overriding Default Marshaling
To declare a method as having an implementation from a DLL export, do the following:
- Declare the method with the static and extern C# keywords.
- Attach the DllImport attribute to the method. The DllImport attribute allows you to specify the name of the DLL that contains the method. The common practice is to name the C# method the same as the exported method, but you can also use a different name for the C# method. DLLs contain export tables of semantically related functions.
- Optionally, specify custom marshaling information for the method's parameters and return value, which will override the .NET Framework default marshaling.
Example 1
This example shows you how to use the DllImport attribute to output a message by calling puts frommsvcrt.dll.
// PInvokeTest.cs
using System;
using System.Runtime.InteropServices;
class PlatformInvokeTest
{
[DllImport("msvcrt.dll")]
public static extern int puts(string c);
[DllImport("msvcrt.dll")]
internal static extern int _flushall(); public static void Main() { puts("Test"); _flushall(); }
}
OutputTest
How it works:
The preceding example shows the minimum requirements for declaring a C# method that is implemented in an unmanaged DLL. The method PlatformInvokeTest.puts is declared with the static and extern modifiers and has the DllImport attribute which tells the compiler that the implementation comes from msvcrt.dll, using the default name of puts. To use a different name for the C# method such as putstring, you must use the EntryPoint option in the DllImport attribute, that is: [DllImport("msvcrt.dll", EntryPoint="puts")].
Default Marshaling and Specifying Custom Marshaling for Parameters toUnmanaged Methods When calling an unmanaged function from C# code, the common language runtime must marshal the parameters and return values. For every .NET Framework type there is a default unmanaged type, which the common language runtime will use to marshal data across a managed to unmanaged function call. For example, the default marshaling for C# string values is to the type LPTSTR (pointer to TCHAR char buffer). You can override the default marshaling using the MarshalAs attribute in the C# declaration of the unmanaged function.
Example 2
This example uses the DllImport attribute to output a string. It also shows you how to override the default marshaling of the function parameters by using the MarshalAs attribute.
// Marshal.cs
using System;
using System.Runtime.InteropServices;
class PlatformInvokeTest
{
[DllImport("msvcrt.dll")]
public static extern int puts([MarshalAs(UnmanagedType.LPStr)] string m);
[DllImport("msvcrt.dll")]
internal static extern int _flushall();
public static void Main()
{
puts("Hello World!"); _flushall();
}
}
Output
When you run this example, the string,
Hello World!
will display on console output.