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 格式。
名稱比對
ExactSpelling欄位預設為true时,在 Visual Basic 中,平台調用只會搜尋您指定的名稱。 例如,如果你指定 MessageBox,平台會呼叫搜尋MessageBox,若找不到精確拼寫則失敗。當
ExactSpelling欄位是false時,如同在 C++ 和 C# 中的預設,平台調用會先搜尋修飾名稱(MessageBoxW),如果找不到修飾名稱,則搜尋未修飾的別名(MessageBox)。 請注意,Unicode 名稱比對行為與 ANSI 名稱比對行為不同。
- Platform invoke 在執行時根據目標平台選擇 ANSI 與 Unicode 格式。
在 Visual Basic 中指定字元集
您可以通過在宣告語句中新增 Ansi、Unicode 或 Auto 關鍵詞,來在 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);
另請參閱
- DllImportAttribute
- 在受控程式碼中建立原型
- 平台調用範例
- 使用平台調用封送處理資料