Поделиться через


Указание набора символов

Поле DllImportAttribute.CharSet управляет маршаллингом строк данных и определяет способ, которым вызов платформы находит имена функций в библиотеке DLL. В этом разделе описывается оба поведения.

Некоторые API экспортируют две версии функций, которые принимают строковые аргументы: узкие (ANSI) и широкие (Юникод). Например, API Windows содержит следующие имена точек входа для функции MessageBox :

  • MessageBoxA

    Предоставляет ANSI форматирование с 1 байтом, отличающееся добавлением "A" к названию точки входа. Вызовы MessageBoxA всегда маршалируют строки в формате ANSI.

  • MessageBoxW

    Предоставляет форматирование 2-байтового символа Юникода, обозначенное добавлением "W" к имени входной точки. Вызовы MessageBoxW всегда маршалируют строки в формате Юникода.

Сопоставление строк и сопоставления имен

Поле CharSet принимает следующие значения:

Ansi (значение по умолчанию)

  • Маршалирование строк

    Платформа вызывает строки маршалов из управляемого формата (Юникод) в формат ANSI.

  • Сопоставление имен

    Когда поле DllImportAttribute.ExactSpelling задано как true, что происходит по умолчанию в Visual Basic, платформа выполняет поиск только указанного вами имени. Например, если указать MessageBox, платформа пытается найти MessageBox и завершается сбоем, если она не может найти точное написание.

    ExactSpelling Когда поле имеет значение false, как это задано по умолчанию в C++ и C#, платформа сначала ищет немодифицированный псевдоним (MessageBox), а затем модифицированное имя (MessageBoxA), если немодифицированный псевдоним не найден. Обратите внимание, что поведение сопоставления имен ANSI отличается от поведения сопоставления имен Юникода.

Unicode

  • Маршалирование строк

    Вызов платформы копирует строки из управляемого формата (Юникод) в формат Юникода.

  • Сопоставление имен

    Когда поле ExactSpelling задано как true, что происходит по умолчанию в Visual Basic, платформа выполняет поиск только указанного вами имени. Например, если указать MessageBox, платформа вызывает функцию MessageBox и выдаёт ошибку, если не может найти точное написание.

    ExactSpelling Когда это поле установлено в false по умолчанию в C++ и C#, при платформенном вызове сначала ищется изменённое имя (MessageBoxW), а затем, если изменённое имя не найдено, неизменённый псевдоним (MessageBox). Обратите внимание, что поведение сопоставления имен Юникода отличается от поведения сопоставления имен ANSI.

Auto

  • Вызов платформы выбирает между форматами ANSI и Юникод во время выполнения в зависимости от целевой платформы.

Указание набора символов в Visual Basic

Вы можете указать поведение набора символов в Visual Basic, добавив ключевое слово Ansi, Unicode или Auto в инструкцию объявления. Если опустить ключевое слово набора символов, 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 или Юникод. Набор символов определяет, как следует маршалировать строковые аргументы метода. Используйте одну из следующих форм, чтобы указать набор символов:

[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, атрибутирующихся для указания набора символов. В первом определении, в случае его отсутствия, поле по умолчанию использует набор символов 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);

См. также