共用方式為


指定字元集

DllImportAttribute.CharSet欄位會控制字串封送處理,並決定平台調用如何在 DLL 中尋找函式名稱。 本主題描述這兩種行為。

某些 API 會匯出兩個採用字串自變數的函式版本:窄 (ANSI) 和寬 (Unicode)。 例如,Windows API 包含以下函式的 MessageBox 入口名稱:

  • MessageBoxA

    提供 1 字節字元 ANSI 格式,以在進入點名稱後附加 "A" 進行區分。 呼叫 MessageBoxA 時,總是以 ANSI 格式封送字串。

  • MessageBoxW

    提供以 「W」 附加至進入點名稱的 2 位元組字元 Unicode 格式。 對 MessageBoxW 的呼叫都會始終以 Unicode 格式編組字串。

字串封送處理和名稱比對

欄位 CharSet 接受下列值:

Ansi (預設值)

  • 字串封送處理

    平台調用方法會將字串從其受控格式(Unicode)封送處理至 ANSI 格式。

  • 名稱比對

    DllImportAttribute.ExactSpelling欄位預設為 true时,在 Visual Basic 中,平台調用只會搜尋您指定的名稱。 例如,如果你指定 MessageBox,平台會呼叫搜尋 MessageBox ,但當找不到確切拼寫時會失敗。

    ExactSpelling當欄位為false時,如同在 C++ 和 C# 中預設,平台調用會先搜尋無修飾的別名(MessageBox),如果找不到無修飾的別名,則會搜尋修飾過的名稱(MessageBoxA)。 請注意,ANSI 名稱比對行為與 Unicode 名稱比對行為不同。

Unicode

  • 字串封送處理

    平台調用會將字串從其管理格式(Unicode)複製到 Unicode 格式。

  • 名稱比對

    ExactSpelling欄位預設為 true时,在 Visual Basic 中,平台調用只會搜尋您指定的名稱。 例如,如果你指定 MessageBox,平台會呼叫搜尋 MessageBox ,若找不到精確拼寫則失敗。

    ExactSpelling欄位是false時,如同在 C++ 和 C# 中的預設,平台調用會先搜尋修飾名稱(MessageBoxW),如果找不到修飾名稱,則搜尋未修飾的別名(MessageBox)。 請注意,Unicode 名稱比對行為與 ANSI 名稱比對行為不同。

Auto

  • Platform invoke 在執行時根據目標平台選擇 ANSI 與 Unicode 格式。

在 Visual Basic 中指定字元集

您可以通過在宣告語句中新增 AnsiUnicodeAuto 關鍵詞,來在 Visual Basic 中指定字元集行為。 如果您省略字元集關鍵詞, DllImportAttribute.CharSet 字段會預設為 ANSI 字元集。

以下範例將 MessageBox 函式宣告了三次,每次具有不同的字元集現象。 第一個語句會省略字元集關鍵詞,因此字元集預設為 ANSI。 第二個和第三個語句會明確指定具有 關鍵詞的字元集。

Friend Class NativeMethods
    Friend Declare Function MessageBoxA Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer

    Friend Declare Unicode Function MessageBoxW Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer

    Friend Declare Auto Function MessageBox Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer
End Class

以 C# 和 C++ 指定字元集

欄位 DllImportAttribute.CharSet 會將基礎字元集識別為 ANSI 或 Unicode。 字元集控制方法中的字串引數應該如何被封送處理。 使用下列其中一種格式來指出字元集:

[DllImport("DllName", CharSet = CharSet.Ansi)]
[DllImport("DllName", CharSet = CharSet.Unicode)]
[DllImport("DllName", CharSet = CharSet.Auto)]
[DllImport("DllName", CharSet = CharSet::Ansi)]
[DllImport("DllName", CharSet = CharSet::Unicode)]
[DllImport("DllName", CharSet = CharSet::Auto)]

以下範例展示了用於指定字元集的三個受管理的MessageBox函數定義。 在第一個定義中,因為疏忽,CharSet 欄位將預設為 ANSI 字元集。

using System;
using System.Runtime.InteropServices;

internal static class NativeMethods
{
    [DllImport("user32.dll")]
    internal static extern int MessageBoxA(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    internal static extern int MessageBoxW(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    internal static extern int MessageBox(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);
}
typedef void* HWND;

// Can use MessageBox or MessageBoxA.
[DllImport("user32")]
extern "C" int MessageBox(
    HWND hWnd, String* lpText, String* lpCaption, unsigned int uType);

// Can use MessageBox or MessageBoxW.
[DllImport("user32", CharSet = CharSet::Unicode)]
extern "C" int MessageBoxW(
    HWND hWnd, String* lpText, String* lpCaption, unsigned int uType);

// Must use MessageBox.
[DllImport("user32", CharSet = CharSet::Auto)]
extern "C" int MessageBox(
    HWND hWnd, String* lpText, String* lpCaption, unsigned int uType);

另請參閱