P/Invoke

From Wikipedia, the free encyclopedia

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

P/Invokeの宣言は、System.Runtime.InteropServices.DllImportAttribute属性をメソッドの宣言につけることで行う。 .NET のバージョン7からはSystem.Runtime.InteropServices.LibraryImportAttribute属性を宣言につけることで、DllImport属性と同じように行える(ただしソースジェネレーターによって効率のよい生成を行ってくれる)。

次の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][2]

また、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
);

また.C++の構造体をC#でマーシャリングを行う場合は、[StructLayout(LayoutKind.Sequential)]を用いる。以下は、Windows APIのPOINT構造体をC#で定義する例である。

[StructLayout(LayoutKind.Sequential)]
struct Point
{
    public int x; // SDKの定義では LONG x; と定義されているが、C#のintに相当する
    public int y; // SDKの定義では LONG y; と定義されているが、C#のintに相当する
};

Windows APIと.NET Frameworkの対応表

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

さらに見る Windows APIでの型名, .NET Frameworkでの型名 ...
Windows APIでの型名.NET Frameworkでの型名C#での型名Visual Basicでの型名
HANDLE(void*) あるいはHBITMAP[注釈 1]などハンドルを表す型名System.IntPtrSystem.IntPtr[注釈 2]System.IntPtr
INT_PTR, LONG_PTRなど(ポインタと同サイズの符号付き整数型)System.IntPtrSystem.IntPtr[注釈 2]System.IntPtr
UINT_PTR, ULONG_PTRなど(ポインタと同サイズの符号無し整数型)System.UIntPtrSystem.UIntPtr[注釈 2]System.UIntPtr
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[注釈 3]Boolean[注釈 4]
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
閉じる


脚注

関連項目

外部リンク

Related Articles

Wikiwand AI