メインメニューを開く

P/Invoke(Platform Invoke、プラットフォーム呼び出し)とは、.NET Frameworkにおける共通言語基盤 (CLI) の機能の一つであり、マネージコードから動的ライブラリ内のネイティブコードを呼び出すことを可能にするものである。受け渡しされるデータ型は、必要であればCLIによって適切に変換されるが、メタデータによってプログラマーが変換方法を指定することもできる。こうしたデータの変換をマーシャリングという。

編集

P/Invokeの宣言は、System.Runtime.InteropServices.DllImportAttribute属性をメソッドの宣言につけることで行う。

次のC#コード例では、user32.dll内に定義されているFindWindow関数を呼び出している。

using System.Runtime.InteropServices;

namespace Example
{
    class ExampleClass
    {
        // FindWindowのアンマネージシグネチャは HWND FindWindow(LPCTSTR, LPCTSTR)
        [DllImport("user32.dll")]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        
        public void Test(string windowName)
        {
            IntPtr hWnd = FindWindow(null, windowName);
            if (hWnd == IntPtr.Zero)
            {
                Console.WriteLine("Window not found.");
            }
            else
            {
                Console.WriteLine("There is a window named " + windowName + ".");
            }
        }
    }
}

このように、P/Invokeで宣言したメソッドは通常のメソッドのように呼び出すことができる。

intdoubleのような型はアンマネージコードが直接解釈することができるため、コピーされずにメモリに固定されたまま直接渡される(blittable型)。一方、stringboolのような型はマネージコードとアンマネージコードとの間で表現方法が異なるため、CLIによって変換処理(マーシャリング)が行われる(非blittable型)[1]

また、DllImportのフィールドを指定することで、文字列のキャラクタセット、呼び出し規約、エラー処理などといった既定の動作を変更することができる。例えば、次の宣言ではメソッド名とは異なる名前の関数を呼び出し対象とするよう指定している。

// ShellExecuteのアンマネージシグネチャは HINSTANCE ShellExecute(HWND, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, INT)
[DllImport("shell32.dll", EntryPoint="ShellExecute")]
static extern IntPtr UnmanagedFunctionWithNewName(
    IntPtr hWnd,
    string lpVerb,
    string lpFile,
    string lpParameters,
    string lpDirectory,
    int nShowCmd
);

Windows APIと.NET Frameworkの対応表編集

以下の表にWindows API (Win32/Win64) での型名[2]、.NET Frameworkでの型名、C#/VBでの型名の対応を示す。

Windows APIでの型名 .NET Frameworkでの型名 C#での型名 Visual Basicでの型名
HANDLE(void*) あるいはHBITMAP[3]などハンドルを表す型名 System.IntPtr System.IntPtr System.IntPtr
INT_PTR, LONG_PTRなど(ポインタと同サイズの整数型) System.IntPtr System.IntPtr System.IntPtr
INT8/SCHAR(signed char) System.SByte sbyte SByte
UINT8/UCHAR/BYTE/BOOLEAN(unsigned char) System.Byte byte Byte
INT16/SHORT(short) System.Int16 short Short
UINT16/USHORT/WORD(unsigned short) System.UInt16 ushort UShort
INT32/INT(int)
LONG32/LONG(long)
System.Int32 int Integer
UINT32/UINT(unsigned int)
ULONG32/ULONG/DWORD(unsigned long)
System.UInt32 uint UInteger
INT64/LONG64/LONGLONG(long long) System.Int64 long Long
UINT64/ULONG64/ULONGLONG(unsigned long long) System.UInt64 ulong ULong
BOOL(int) System.Boolean bool[4] Boolean[5]
CHAR(char) System.Byte/System.SByte byte/sbyte Byte/SByte
WCHAR(wchar_t) System.Char char Char
LPSTR(char*)
LPWSTR (wchar_t*)
System.Text.StringBuilder System.Text.StringBuilder System.Text.StringBuilder
LPCSTR(const char*)
LPCWSTR(const wchar_t*)
System.String string String
FLOAT(float) System.Single float Single
DOUBLE(double) System.Double double Double

外部リンク編集

脚注編集

  1. ^ Blittable 型と非 Blittable 型
  2. ^ Windows Data Types - Windows applications | Microsoft Docs
  3. ^ STRICTシンボル定義の有無によって変化するが、ポインタ型であることに変わりはない。
  4. ^ sizeof(bool)の結果は1だが、System.Runtime.InteropServices.Marshal.SizeOf(typeof(bool))の結果は4となる。
  5. ^ Len(New Boolean)の結果は2だが、System.Runtime.InteropServices.Marshal.SizeOf(GetType(Boolean))の結果は4となる。