Share via


指定字符集

DllImportAttribute.CharSet 字段控制字符串封送处理并确定平台调用在 DLL 中查找函数名的方式。 本主题将介绍这两种行为。

对于采用字符串参数的函数,有些 API 将导出它们的两个版本:窄版本 (ANSI) 和宽版本 (Unicode)。 例如,Win32 API 包含 MessageBox 函数的以下入口点名称:

  • MessageBoxA

    提供单字节字符 ANSI 格式,其特征是在入口点名称后附加一个“A”。 对 MessageBoxA 的调用始终会以 ANSI 格式封送字符串,它常见于 Windows 95 和 Windows 98 平台。

  • MessageBoxW

    提供双字节字符 Unicode 格式,其特征是在入口点名称后附加一个“W”。 对 MessageBoxW 的调用始终会以 Unicode 格式封送字符串,它常见于 Windows NT、Windows 2000 和 Windows XP 平台。

字符串封送处理和名称匹配

CharSet 字段接受以下值:

CharSet.Ansi(默认值)

  • 字符串封送处理

    平台调用将字符串从托管格式 (Unicode) 封送为 ANSI 格式。

  • 名称匹配

    DllImportAttribute.ExactSpelling 字段为 true(它是 Visual Basic 2005 中的默认值)时,平台调用将只搜索您指定的名称。 例如,如果指定 MessageBox,则平台调用将搜索 MessageBox,如果它找不到完全相同的拼写则失败。

    ExactSpelling 字段为 false(它是 C++ 和 C# 中的默认值)时,平台调用将首先搜索未处理的别名 (MessageBox),如果找不到未处理的别名,则将搜索已处理的名称 (MessageBoxA)。 请注意,ANSI 名称匹配行为与 Unicode 名称匹配行为不同。

CharSet.Unicode

  • 字符串封送处理

    平台调用会将字符串从托管格式 (Unicode) 复制为 Unicode 格式。

  • 名称匹配

    ExactSpelling 字段为 true(它是 Visual Basic 2005 中的默认值)时,平台调用将只搜索您指定的名称。 例如,如果指定 MessageBox,则平台调用将搜索 MessageBox,如果它找不到完全相同的拼写则失败。

    ExactSpelling 字段为 false(它是 C++ 和 C# 中的默认值)时,平台调用将首先搜索已处理的名称 (MessageBoxW),如果找不到已处理的名称,则将搜索未处理的别名 (MessageBox)。 请注意,Unicode 名称匹配行为与 ANSI 名称匹配行为不同。

CharSet.Auto

  • 平台调用在运行时根据目标平台在 ANSI 和 Unicode 格式之间进行选择。

在 Visual Basic 中指定字符集

下面的示例三次声明 MessageBox 函数,每次都具有不同的字符集行为。 可以在 Visual Basic 中指定字符集行为,方法是向声明语句中添加 AnsiUnicodeAuto 关键字。

如果省略字符集关键字(第一个声明语句中就是这样做的),则 DllImportAttribute.CharSet 字段默认为 ANSI 字符集。 该示例中的第二个语句和第三个语句则使用关键字显式指定字符集。

Imports System.Runtime.InteropServices

Public Class Win32
   Declare Function MessageBoxA Lib "user32.dll"(ByVal hWnd As Integer, _
       ByVal txt As String, ByVal caption As String, _
       ByVal Typ As Integer) As Integer

   Declare Unicode Function MessageBoxW Lib "user32.dll" _
       (ByVal hWnd As Integer, ByVal txt As String, _
        ByVal caption As String, ByVal Typ As Integer) As Integer

   Declare Auto Function MessageBox Lib "user32.dll" _
       (ByVal hWnd As Integer, ByVal txt As String, _
        ByVal caption As String, ByVal Typ As Integer) 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 字符集。

[DllImport("user32.dll")]
    public static extern int MessageBoxA(int hWnd, String text, 
        String caption, uint type);
[DllImport("user32.dll", CharSet=CharSet.Unicode)]
    public static extern int MessageBoxW(int hWnd, String text, 
        String caption, uint type);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
    public static extern int MessageBox(int hWnd, String text, 
        String caption, uint type);
typedef void* HWND;

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

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

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

请参见

参考

DllImportAttribute

概念

在托管代码中创建原型

平台调用示例

其他资源

用平台调用封送数据