P/Invoke

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.IntPtrSystem.IntPtrSystem.IntPtr
INT_PTR, LONG_PTRなど(ポインタと同サイズの整数型)System.IntPtrSystem.IntPtrSystem.IntPtr
INT8/SCHAR(signed char)System.SBytesbyteSByte
UINT8/UCHAR/BYTE/BOOLEAN(unsigned char)System.BytebyteByte
INT16/SHORT(short)System.Int16shortShort
UINT16/USHORT/WORD(unsigned short)System.UInt16ushortUShort
INT32/INT(int)
LONG32/LONG(long)
System.Int32intInteger
UINT32/UINT(unsigned int)
ULONG32/ULONG/DWORD(unsigned long)
System.UInt32uintUInteger
INT64/LONG64/LONGLONG(long long)System.Int64longLong
UINT64/ULONG64/ULONGLONG(unsigned long long)System.UInt64ulongULong
BOOL(int)System.Booleanbool[4]Boolean[5]
CHAR(char)System.Byte/System.SBytebyte/sbyteByte/SByte
WCHAR(wchar_t)System.CharcharChar
LPSTR(char*)
LPWSTR (wchar_t*)
System.Text.StringBuilderSystem.Text.StringBuilderSystem.Text.StringBuilder
LPCSTR(const char*)
LPCWSTR(const wchar_t*)
System.StringstringString
FLOAT(float)System.SinglefloatSingle
DOUBLE(double)System.DoubledoubleDouble

外部リンク

脚注

  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となる。
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.