Пример буферов

В этом примере показан способ передачи строк в виде параметров In/Out управляемым функциям, ожидающим в качестве параметра функции строку (LPSTR). Затем показано использование строки, возвращаемой неуправляемым методом в случае, когда вызывающий объект, как предполагается, не освобождает выделенную для строки память.

В этом примере платформа вызывает две собственных функции Win32, экспортированных из Kernel32.dll:

  • GetSystemDirectory

    Возвращает путь к системному каталогу.

  • GetCommandLine

    Возвращает командную строку для текущего процесса.

Класс LibWrap содержит управляемый прототип для неуправляемых функций, вызываемых из функции Main консольного приложения. Поле CharSet задано таким образом, что при вызове неуправляемого кода во время выполнения имелась возможность выбора одного из двух форматов (ANSI или Юникод) в зависимости от целевой платформы. Дополнительные сведения об этом поле см. в разделе Определение кодировки.

Метод прототипа GetSystemDirectory заменяет буфер StringBuilder для неуправляемого типа LPSTR. Размер буфера остается неизменным. Для соответствия требованиям исходной функции метод GetSystemDirectory в качестве второго аргумента передает переменную, содержащую размер буфера. Тип LPTSTR в объявлении заменяется буфером StringBuilder, а не строкой. В отличие от строк, которые неизменяемы, буферы StringBuilder могут быть изменены.

Собственная функция GetCommandLine возвращает указатель на буфер, выделенный операционной системой, которая является его владельцем. При маршалинге строк, как возвращаемых типов, упаковщик взаимодействия, что он должен с помощью функции освободить память, на которую указывал исходный тип LPTSTR. Чтобы предотвратить автоматическую очистку памяти упаковщиком, управляемый прототип GetCommandLine возвращает вместо строки тип IntPtr. Метод PtrToStringAuto копирует неуправляемый тип LPSTR в управляемый объект строки, при необходимости расширяя формат символа.

Объявление прототипов

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

Вызов функций

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

См. также

Основные понятия

Маршалинг строк

Типы данных вызовов неуправляемого кода

Маршалинг по умолчанию для строк

Другие ресурсы

Creating Prototypes in Managed Code