文字セットを指定する

DllImportAttribute.CharSet フィールドは文字列のマーシャリングを制御し、DLL の関数名をプラットフォーム呼び出しが見つけるしくみを決定します。 このトピックでは、両方の動作について説明します。

一部の API は、文字列引数、ナロー (ANSI) とワイド (Unicode) を受け取る 2 種類の関数をエクスポートします。 たとえば、Windows API には、MessageBox 関数の次のエントリ ポイント名が含まれています。

  • MessageBoxA

    1 バイト文字の ANSI 書式設定を提供します。エントリ ポイント名に "A" が追加されます。 MessageBoxA を呼び出すと、常に ANSI 形式で文字列がマーシャリングされます。

  • MessageBoxW

    2 バイト文字の Unicode 書式設定を提供します。エントリ ポイント名に "W" が追加されます。 MessageBoxW を呼び出すと、常に Unicode 形式で文字列がマーシャリングされます。

文字列のマーシャリングと名前の一致

CharSet フィールドは次の値を受け取ります。

Ansi (既定値)

  • 文字列のマーシャリング

    プラットフォーム呼び出しは、その管理対象形式 (Unicode) から ANSI 形式に文字列をマーシャリングします。

  • 名前の一致

    DllImportAttribute.ExactSpelling フィールドが true の場合 (Visual Basic ではこれが既定値)、プラットフォーム呼び出しによって指定した名前のみが検索されます。 たとえば、MessageBox を指定した場合、プラットフォーム呼び出しは MessageBox を検索し、厳密に一致する綴りが見つからない場合、検索失敗となります。

    ExactSpelling フィールドが false のとき (C++ と C# で既定)、プラットフォーム呼び出しは最初に修飾なしのエイリアスを探し (ExactSpelling)、見つからなければ、修飾ありの名前を探します (false)。 ANSI の名前一致動作と Unicode の名前一致動作は異なることにご注意ください。

Unicode

  • 文字列のマーシャリング

    プラットフォーム呼び出しは、その管理対象形式 (Unicode) から Unicode 形式に文字列をコピーします。

  • 名前の一致

    ExactSpelling フィールドが true の場合 (Visual Basic ではこれが既定値)、プラットフォーム呼び出しによって指定した名前のみが検索されます。 たとえば、MessageBox を指定した場合、プラットフォーム呼び出しは MessageBox を検索し、厳密に一致する綴りが見つからない場合、検索失敗となります。

    ExactSpelling フィールドが false のとき (C++ と C# で既定)、プラットフォーム呼び出しは最初に修飾ありの名前を探し (ExactSpelling)、見つからなければ、修飾なしのエイリアスを探します (false)。 Unicode の名前一致動作と ANSI の名前一致動作は異なることにご注意ください。

Auto

  • プラットフォーム呼び出しは、対象プラットフォームに基づき、ANSI 形式または Unicode 形式を選択します。

Visual Basic で文字セットを指定する

Visual Basic では、文字セット動作を指定できます。宣言ステートメントにキーワードとして AnsiUnicodeAuto を追加します。 文字セット キーワードを省略した場合、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 を識別します。 この文字セットは、メソッドの文字列引数をマーシャリングする方法を制御します。 次の形式の 1 つを使用し、文字セットを指示します。

[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);

関連項目