P/Invoke
From Wikipedia, the free encyclopedia
例
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で宣言したメソッドは通常のメソッドのように呼び出すことができる。
intやdoubleのような型はアンマネージコードが直接解釈することができるため、コピーされずにメモリに固定されたまま直接渡される(blittable型)。一方、stringやboolのような型はマネージコードとアンマネージコードとの間で表現方法が異なるため、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 |