Ejemplo Buffers

En este ejemplo se muestra cómo pasar cadenas como parámetros In/Out a funciones no administradas que esperan recibir una cadena (LPSTR) como un parámetro de función. Además, se muestra cómo utilizar una cadena devuelta desde un método no administrado en el caso especial en que no se espera que el llamador libere la memoria asignada para la cadena.

Esta plataforma de ejemplo invoca dos funciones de Win32 nativas exportadas de Kernel32.dll:

  • GetSystemDirectory

    Recupera la ruta de acceso del directorio del sistema.

  • GetCommandLine

    Recupera la cadena de la línea de comandos para el proceso actual.

La clase LibWrap contiene prototipos administrados para las funciones no administradas, a las que se llama desde Principal en la aplicación de consola. El campo CharSet está configurado de forma que la invocación de plataforma pueda elegir entre los formatos ANSI y Unicode en tiempo de ejecución, en función de la plataforma de destino. Para obtener más información sobre este campo, vea Especificar un juego de caracteres.

En el método de prototipo GetSystemDirectory, se reemplaza el tipo LPSTR no administrado por un búfer StringBuilder. El tamaño del búfer permanece fijo. Para adaptarse a los requisitos de la función original, GetSystemDirectory pasa la variable del tamaño del búfer como segundo argumento. En la declaración, el tipo LPTSTR se reemplaza por un búfer StringBuilder, en lugar de por una cadena. A diferencia de las cadenas, que son inmutables, los búferes StringBuilder se pueden cambiar.

La función GetCommandLine nativa devuelve un puntero a un búfer que está asignado y pertenece al sistema operativo. Al calcular las referencias de cadenas como tipos devueltos, el contador de referencias de interoperabilidad supone que debe liberar la memoria a la que apuntaba el tipo LPTSTR original en la función. Para evitar que el contador de referencias reclame automáticamente esta memoria, el prototipo administrado GetCommandLine devuelve un tipo IntPtr en lugar de una cadena. El método PtrToStringAuto copia el tipo LPSTR no administrado en un objeto de cadena administrado, lo que amplía el formato de los caracteres, si es necesario.

Declaración de prototipos

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();
}
public ref class LibWrap
{
public:
    [DllImport("Kernel32.dll", CharSet=CharSet::Auto)]
    static int GetSystemDirectory(StringBuilder^
        sysDirBuffer, int size);

    [DllImport("Kernel32.dll", CharSet=CharSet::Auto)]
    static IntPtr GetCommandLine();
};

Llamadas a funciones

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);
    }
}
public ref class App
{
public:
    static void Main()
    {
        // Call GetSystemDirectory.
        StringBuilder^ sysDirBuffer = gcnew StringBuilder(256);
        LibWrap::GetSystemDirectory(sysDirBuffer, sysDirBuffer->Capacity);
        // ...
        // Call GetCommandLine.
        IntPtr cmdLineStr = LibWrap::GetCommandLine();
        String^ commandLine = Marshal::PtrToStringAuto(cmdLineStr);
    }
};

Vea también

Conceptos

Calcular referencias de cadenas

Tipos de datos de invocación de plataforma

Cálculo de referencias predeterminado para cadenas

Otros recursos

Creating Prototypes in Managed Code