P/Invoke

P/Invoke(Platform Invoke、プラットフォーム呼び出し)とは、.NET Frameworkにおける共通言語基盤 (CLI) の機能の一つであり、�…

P/Invoke

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での型名 C#での型名 Visual Basicでの型名
HANDLE(void*) あるいはHBITMAP[注釈 1]などハンドルを表す型名 System.IntPtr System.IntPtr[注釈 2] System.IntPtr
INT_PTR, LONG_PTRなど(ポインタと同サイズの符号付き整数型) System.IntPtr System.IntPtr[注釈 2] System.IntPtr
UINT_PTR, ULONG_PTRなど(ポインタと同サイズの符号無し整数型) System.UIntPtr System.UIntPtr[注釈 2] System.UIntPtr
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[注釈 3] Boolean[注釈 4]
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. ^ STRICTシンボル定義の有無によって変化するが、ポインタ型であることに変わりはない。
  2. ^ a b c C# 9.0以降はnintキーワードおよびnuintキーワードが用意されている[4]
  3. ^ sizeof(bool)の結果は1だが、System.Runtime.InteropServices.Marshal.SizeOf(typeof(bool))の結果は4となる。
  4. ^ Len(New Boolean)の結果は2だが、System.Runtime.InteropServices.Marshal.SizeOf(GetType(Boolean))の結果は4となる。

出典

関連項目

外部リンク

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.