“缓冲区”示例

此示例演示如何将字符串作为 In/Out 参数传递给需要字符串 (LPSTR) 作为函数参数的非托管函数。 此外,它还显示在调用方不释放为该字符串分配的内存的特殊情况下,如何使用从非托管方法返回的字符串。

此示例平台调用从 Kernel32.dll 导出的两个本机 Win32 函数:

  • GetSystemDirectory

    检索系统目录的路径。

  • GetCommandLine

    检索当前进程的命令行字符串。

LibWrap 类包含非托管函数的托管原型,从控制台应用程序中的“Main”调用。 CharSet 字段设置为使平台调用可以在运行时根据目标平台在 ANSI 与 Unicode 格式之间进行选择。 有关此字段的更多信息,请参见指定字符集

GetSystemDirectory 原型方法用 StringBuilder 缓冲区替换非托管 LPSTR 类型。 缓冲区大小保持固定。 为满足原始函数的要求,GetSystemDirectory 将缓冲区大小变量作为第二个参数来传递。 一个 StringBuilder 缓冲区(而非一个字符串)替换声明中的 LPTSTR 类型。 与不可变的字符串不同,StringBuilder 缓冲区可以更改。

本机 GetCommandLine 函数返回指向由操作系统分配和拥有的缓冲区的指针。 当将字符串作为返回类型进行封送处理时,Interop 封送拆收器将假定它必须释放由原始 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