Sdílet prostřednictvím


Buffers Sample 

This sample shows how to pass strings as In/Out parameters to unmanaged functions that expect a string (LPSTR) as a function parameter. Further, it shows how to use a string returned from an unmanaged method in the special case where the caller is not supposed to free memory allocated for the string.

This sample platform invokes two native Win32 functions exported from Kernel32.dll:

  • GetSystemDirectory

    Retrieves the path of the system directory.

  • GetCommandLine

    Retrieves the command-line string for the current process.

The LibWrap class contains a managed prototypes for the unmanaged functions, which are called from Main in the console application. The CharSet Specifying a Character Setfield is set so that platform invoke can choose between ANSI and Unicode formats at run time, based on the target platform. For more information about this field, see Specifying a Character Set.

The GetSystemDirectory prototype method substitutes a StringBuilder buffer for the unmanaged LPSTR type. The buffer size remains fixed. To accommodate the requirements of the original function, GetSystemDirectory passes the buffer size variable as the second argument. A StringBuilder buffer, rather than a string, replaces the LPTSTR type in the declaration. Unlike strings, which are immutable, StringBuilder buffers can be changed.

The native GetCommandLine function returns a pointer to a buffer allocated and owned by the operating system. When marshaling strings as return types, the interop marshaler assumes it must free the memory that the original LPTSTR type pointed to by the function. To prevent the marshaler from automatically reclaiming this memory, the managed GetCommandLine prototype returns an IntPtr type instead of a string. The PtrToStringAuto method copies the unmanaged LPSTR type to a managed string object, widening the character format, if required.

The source code for the following code examples is provided by the .NET Framework Platform Invoke Technology Sample.

Declaring Prototypes

Public Class LibWrap
   Declare Auto Sub GetSystemDirectory Lib "Kernel32.dll" _
      ( ByVal sysDirBuffer As StringBuilder, ByVal buffSize As Integer )
   Declare Auto Function GetCommandLine Lib "Kernel32.dll" () As IntPtr
End Class
public class LibWrap
{
   [ DllImport( "Kernel32.dll", CharSet=CharSet.Auto )]
   public static extern int GetSystemDirectory( StringBuilder 
      sysDirBuffer, int size );
   [ DllImport( "Kernel32.dll", CharSet=CharSet.Auto )] 
   public static extern IntPtr GetCommandLine();   
}

Calling Functions

Public Class App
   Public Shared Sub Main()
      ' Call GetSystemDirectory.
      Dim sysDirBuffer As New StringBuilder( 256 )
      LibWrap.GetSystemDirectory( sysDirBuffer, sysDirBuffer.Capacity )
      …
      ' Call GetCommandLine.
      Dim cmdLineStr As IntPtr = LibWrap.GetCommandLine()
      Dim commandLine As String = Marshal.PtrToStringAuto( cmdLineStr )
   End Sub
End Class
public class App
{
   public static void Main()
   {
      // Call GetSystemDirectory.
      StringBuilder sysDirBuffer = new StringBuilder( 256 );
      LibWrap.GetSystemDirectory( sysDirBuffer, sysDirBuffer.Capacity );
      …
      // Call GetCommandLine.
      IntPtr cmdLineStr = LibWrap.GetCommandLine();
      String commandLine = Marshal.PtrToStringAuto( cmdLineStr );
   }
}

See Also

Tasks

Platform Invoke Technology Sample

Concepts

Marshaling Strings
Platform Invoke Data Types
Default Marshaling for Strings
Creating Prototypes in Managed Code