Beispiel für Puffer

Dieses Beispiel veranschaulicht, wie Zeichenfolgen als In/Out-Parameter an nicht verwaltete Funktionen übergeben werden, die als Funktionsparameter eine Zeichenfolge (LPSTR) erwarten. Darüber hinaus wird gezeigt, wie eine durch eine nicht verwaltete Methode zurückgegebene Zeichenfolge in einem speziellen Fall zu verwenden ist, in dem der Aufrufer keinen für die Zeichenfolge belegten Speicher freigeben soll.

Diese Beispielplattform ruft zwei von Kernel32.dll exportierte systemeigene Win32-Funktionen auf:

  • GetSystemDirectory

    Ruft den Pfad des Systemverzeichnisses ab.

  • GetCommandLine

    Ruft die Befehlszeilenzeichenfolge für den aktuellen Prozess ab.

Die LibWrap-Klasse enthält verwaltete Prototypen für die nicht verwalteten Funktionen, die von Main in der Konsolenanwendung aufgerufen werden. Das CharSet-Feld wird so festgelegt, dass der Plattformaufruf basierend auf der Zielplattform zur Laufzeit zwischen den Formaten ANSI und Unicode wählen kann. Weitere Informationen über dieses Tool finden Sie unter Angeben eines Zeichensatzes.

Die GetSystemDirectory-Prototypmethode verwendet einen StringBuilder-Puffer anstelle des nicht verwalteten LPSTR-Typs. Die Puffergröße bleibt unverändert. Um die Anforderungen der ursprünglichen Funktion zu berücksichtigen, übergibt GetSystemDirectory die Puffergrößenvariable als zweites Argument. Anstelle einer Zeichenfolge ersetzt ein StringBuilder-Puffer den LPTSTR-Typ in der Deklaration. Im Gegensatz zu den unveränderlichen Zeichenfolgen können StringBuilder-Puffer geändert werden.

Die systemeigene GetCommandLine-Funktion gibt einen Zeiger auf einen Puffer zurück, der durch das Betriebssystem zugewiesen wird und dessen Eigentümer das Betriebssystem ist. Beim Marshallen von Zeichenfolgen als Rückgabetypen geht der Interop-Marshaller davon aus, dass er den Speicher freigeben muss, auf den der ursprüngliche LPTSTR-Typ über die Funktion verwiesen hat. Um zu verhindern, dass der Marshaller diesen Speicher zurückfordert, gibt der verwaltete Prototyp GetCommandLine anstelle einer Zeichenfolge einen IntPtr-Typ zurück. Die PtrToStringAuto-Methode kopiert den nicht verwalteten LPSTR-Typ in ein verwaltetes Zeichenfolgenobjekt, wobei gegebenenfalls das Zeichenformat erweitert wird.

Deklarieren von Prototypen

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

Aufrufen von Funktionen

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

Siehe auch

Konzepte

Marshallen von Zeichenfolgen

Datentypen für den Plattformaufruf

Standardmäßiges Marshalling für Zeichenfolgen

Weitere Ressourcen

Creating Prototypes in Managed Code