Export (0) Print
Expand All

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 field 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.

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();
}

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);
    }
}
Show:
© 2014 Microsoft