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