缓冲区示例

更新:2007 年 11 月

此示例演示如何将字符串作为 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 类型复制到托管字符串对象,从而扩展字符格式。

下面的代码示例的源代码由 .NET Framework 平台调用技术示例提供。

声明原型

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

请参见

任务

平台调用技术示例

概念

封送字符串

平台调用数据类型

字符串的默认封送处理

在托管代码中创建原型