次の方法で共有


文字セットを指定する

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) から Unicode 形式にコピーされます。

  • 名前の一致

    ExactSpelling フィールドが Visual Basic の既定でtrueされている場合、プラットフォーム呼び出しでは指定した名前のみが検索されます。 たとえば、 MessageBox を指定した場合、プラットフォームは MessageBox の検索を呼び出し、正確なスペルが見つからない場合は失敗します。

    ExactSpelling フィールドが C++ および C# で既定でfalseされている場合、プラットフォーム呼び出しでは、まずマングルされた名前 (MessageBoxW) を検索し、マングルされた名前が見つからない場合は、マングルされていないエイリアス (MessageBox) を検索します。 Unicode の名前一致動作は、ANSI の名前一致動作とは異なる点に注意してください。

Auto

  • プラットフォーム呼び出しでは、ターゲット プラットフォームに基づいて、実行時に ANSI 形式と Unicode 形式を選択します。

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

Visual Basic では、 AnsiUnicode、または 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);

こちらも参照ください