DllImportAttribute.CharSet フィールドは、文字列マーシャリングを制御し、プラットフォーム呼び出しで DLL 内の関数名を検索する方法を決定します。 このトピックでは、両方の動作について説明します。
一部の API では、文字列引数を受け取る関数の 2 つのバージョン (narrow (ANSI) と wide (Unicode) がエクスポートされます。 たとえば、Windows API には、 MessageBox 関数の次のエントリ ポイント名が含まれています。
MessageBoxA
エントリ ポイント名に付加された "A" で識別される 1 バイト文字の ANSI 書式を提供します。 MessageBoxA の呼び出しは、常に ANSI 形式で文字列をマーシャリングします。
MessageBoxW
エントリ ポイント名に追加された "W" で識別される 2 バイト文字の Unicode 書式を提供します。 MessageBoxW の呼び出しでは、常に Unicode 形式で文字列がマーシャリングされます。
文字列のマーシャリングと名前の一致
CharSet フィールドには、次の値を指定できます。
Ansi (既定値)
文字列のマーシャリング
プラットフォームは、マネージド形式 (Unicode) から ANSI 形式へのマーシャリング文字列を呼び出します。
名前の一致
DllImportAttribute.ExactSpelling フィールドが Visual Basic の既定で
trueされている場合、プラットフォーム呼び出しでは指定した名前のみが検索されます。 たとえば、 MessageBox を指定した場合、プラットフォームは MessageBox の検索を呼び出し、正確なスペルが見つからない場合は失敗します。ExactSpellingフィールドが C++ および C# で既定でfalseされている場合、プラットフォーム呼び出しでは、未管理のエイリアスが見つからない場合は、最初に管理されていないエイリアス (MessageBox)、次にマングルされた名前 (MessageBoxA) が検索されます。 ANSI の名前一致動作は、Unicode の名前照合動作とは異なる点に注意してください。
文字列のマーシャリング
プラットフォーム呼び出しでは、文字列がマネージド形式 (Unicode) から Unicode 形式にコピーされます。
名前の一致
ExactSpellingフィールドが Visual Basic の既定でtrueされている場合、プラットフォーム呼び出しでは指定した名前のみが検索されます。 たとえば、 MessageBox を指定した場合、プラットフォームは MessageBox の検索を呼び出し、正確なスペルが見つからない場合は失敗します。ExactSpellingフィールドが C++ および C# で既定でfalseされている場合、プラットフォーム呼び出しでは、まずマングルされた名前 (MessageBoxW) を検索し、マングルされた名前が見つからない場合は、マングルされていないエイリアス (MessageBox) を検索します。 Unicode の名前一致動作は、ANSI の名前一致動作とは異なる点に注意してください。
- プラットフォーム呼び出しでは、ターゲット プラットフォームに基づいて、実行時に ANSI 形式と Unicode 形式を選択します。
Visual Basic で文字セットを指定する
Visual Basic では、 Ansi、 Unicode、または Auto キーワードを宣言ステートメントに追加することで、文字セットの動作を指定できます。 文字セット キーワードを省略すると、 DllImportAttribute.CharSet フィールドの既定値は ANSI 文字セットになります。
次の例では、 MessageBox 関数を 3 回宣言します。そのたびに、文字セットの動作が異なります。 最初のステートメントでは文字セット キーワードが省略されているため、文字セットは既定で ANSI に設定されます。 2 番目と 3 番目のステートメントでは、キーワードを使用して文字セットを明示的に指定します。
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 関数の 3 つのマネージド定義を示しています。 最初の定義では、省略により、 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);
こちらも参照ください
.NET