Определение кодировки
Поле DllImportAttribute.CharSet управляет маршаллингом строк и определяет, как вызов платформы находит имена функций в библиотеке DLL. В этом разделе описываются оба механизма.
Некоторые API экспортируют две версии функций, которые принимают строковые аргументы: обычные (ANSI) и двухбайтовые (Юникод). Например, API Windows включает следующие имена точек входа для функции MessageBox:
MessageBoxA
Обеспечивает форматирование однобайтовых символов ANSI и имеет суффикс "A" в имени точки входа. При вызове MessageBoxA строки всегда маршалируются в формате ANSI.
MessageBoxW
Обеспечивает форматирование двухбайтовых символов Юникода и имеет суффикс "W" в имени точки входа. При вызове MessageBoxW строки всегда маршалируются в формате Юникод.
Сопоставление строк и сопоставления имен
Поле CharSet
принимает следующие значения:
Ansi (значение по умолчанию)
Маршалирование строк
При вызове неуправляемого кода выполняется маршалинг строк из соответствующего управляемого формата (Юникод) в формат ANSI.
Сопоставление имен
Если поле DllImportAttribute.ExactSpelling имеет значение
true
(значение по умолчанию в Visual Basic), при вызове неуправляемого кода осуществляется поиск только указанного имени. Например, если указать MessageBox, при вызове неуправляемого кода будет выполнен поиск MessageBox, который может завершиться сбоем из-за невозможности найти точное совпадение.Если поле
ExactSpelling
имеет значениеfalse
(по умолчанию для C++ и C#), при вызове неуправляемого кода выполняется поиск сначала неуправляемого псевдонима (MessageBox), а затем, если неуправляемый псевдоним не найден, управляемого имени (MessageBoxA). Обратите внимание, что принципы сопоставления имен ANSI и Юникода различаются.
Маршалирование строк
При вызове неуправляемого кода строки копируются из соответствующего управляемого формата (Юникод) в формат Юникода.
Сопоставление имен
Если поле
ExactSpelling
имеет значениеtrue
(значение по умолчанию в Visual Basic), при вызове неуправляемого кода осуществляется поиск только указанного имени. Например, если указать MessageBox, при вызове неуправляемого кода будет выполнен поиск MessageBox, который может завершиться сбоем из-за невозможности найти точное совпадение.Если поле
ExactSpelling
имеет значениеfalse
(по умолчанию для C++ и C#), при вызове неуправляемого кода выполняется поиск сначала управляемого имени (MessageBoxW), а затем, если управляемое имя не найдено, неуправляемого псевдонима (MessageBox). Обратите внимание, что принципы сопоставления имен Юникода и ANSI различаются.
- При вызове неуправляемого кода во время выполнения осуществляется выбор между форматами 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 с атрибутами, задающими кодировку. В первом определении соответствующее ключевое слово опущено, в результате чего в поле 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);