緩衝區範例

這個範例示範如何將字串當成 In/Out 參數,傳遞至預期將字串 (LPSTR) 做為函式參數的 Unmanaged 函式。 此外,它顯示如何在呼叫端不支援釋放為該字串配置之記憶體的特殊情況下,使用 Unmanaged 方法傳回的字串。

這個範例會平台叫用從 Kernel32.dll 匯出的兩個原生 Win32 函式:

  • GetSystemDirectory

    擷取系統目錄的路徑。

  • GetCommandLine

    擷取目前處理序的命令列字串。

LibWrap 類別 (Class) 包含 Unmanaged 函式的 Managed 原型 (Prototype),該函式的呼叫是從主控台應用程式中的 Main 進行的。 CharSet 欄位的設定,使得平台叫用可以根據目標平台,而在執行階段於 ANSI 和 Unicode 格式之間選擇。 如需此欄位的詳細資訊,請參閱指定字元集

GetSystemDirectory 原型方法會以 StringBuilder 緩衝區替代 Unmanaged LPSTR 型別。 而該緩衝區大小會保持固定。 若要符合原始函式的需求,GetSystemDirectory 會傳遞緩衝區大小變數做為第二個引數。 StringBuilder 緩衝區 (而非字串),會在宣告中取代 LPTSTR 型別。 不同於不變的字串,StringBuilder 緩衝區是可以變更的。

原生 GetCommandLine 函式會傳回作業系統所配置和擁有的緩衝區指標。 將字串封送處理為傳回型別時,Interop 封送處理器會假設它必須釋放由函式指向之原始 LPTSTR 型別的記憶體。 為了避免封送處理器自動回收此記憶體,Managed GetCommandLine 原型會傳回 IntPtr 型別,而非字串。 PtrToStringAuto 方法會將 Unmanaged LPSTR 型別複製到 Managed 字串物件,並在需要時擴大字元格式。

宣告原型

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