最終更新:2021-10-09 (土) 07:53:26 (945d)
DllImport
Top / DllImport
DllImportAttribute
- 属性付きメソッドがアンマネージ ダイナミックリンク ライブラリ (DLL) によって静的エントリ ポイントとして公開されることを示します。
プラットフォーム呼び出し
- プラットフォーム呼び出し/データ型
- プラットフォーム呼び出し/ポインタ
- プラットフォーム呼び出し/コールバック
- プラットフォーム呼び出し/文字列
- プラットフォーム呼び出し/構造体
- プラットフォーム呼び出し/配列
例
- Kernal32.dllに含まれるAPIである
DWORD GetTickCount()
- をC#から使用できるようにする場合
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace MarshalSample { class MarshalWin32API { [DllImport("Kernel32.dll")] public static extern UInt32 GetTickCount(); } } //呼び出し uint tick = MarshalWin32API.GetTickCount();
構文
- DllImport属性を付けたWin32 APIやDLL関数の宣言では、関数の実体が外部にあることを表すextern修飾子と、静的なメンバであることを表すstatic修飾子を必ず指定する。なお、ここではpublicやprivateなどのアクセス修飾子は省略したが、必要であれば指定することもできる。
[DllImport("kernel32.dll")] extern static bool Beep(uint dwFreq, uint dwDuration);
フィールド
BestFitMapping?
CallingConvention
CharSet
- https://docs.microsoft.com/ja-jp/dotnet/framework/interop/specifying-a-character-set
CharSet.Ansi? ANSI (既定値) CharSet.Unicode Unicode CharSet.Auto?
EntryPoint?
- EntryPoint? 引数がない場合、デフォルト値は関数の名前になります。
ExactSpelling?
PreserveSig?
SetLastError
ThrowOnUnmappableChar?
例
DLL関数に文字列を渡す場合
[DllImport("kernel32.dll", CharSet=CharSet.Auto)] extern static bool SetConsoleTitle(string lpConsoleTitle);
DLL関数に文字列バッファを渡す場合
[DllImport("kernel32.dll")] private static extern uint GetConsoleTitle(StringBuilder lpConsoleTitle, uint nSize); static void Main() { StringBuilder buf = new StringBuilder(256); GetConsoleTitle(buf, (uint)(buf.Capacity)); Console.WriteLine(buf.ToString()); // 出力例: コマンド プロンプト - gettitle }
DLL関数に構造体を渡す場合
- StructLayoutを使う
[StructLayout(LayoutKind.Sequential)] struct POINT { public int x; public int y; } [StructLayout(LayoutKind.Sequential)] struct RECT { public int left; public int top; public int right; public int bottom; } class PointInRect { [DllImport("user32.dll")] private static extern bool PtInRect(ref RECT r, POINT p); private static int ReadValue(string prompt) { Console.Write(prompt + " = "); return Int32.Parse(Console.ReadLine()); } private static void Main() { RECT r; POINT p; p.x = ReadValue("点のx座標"); p.y = ReadValue("点のy座標"); r.left = ReadValue("長方形の左上隅のx座標"); r.top = ReadValue("長方形の左上隅のy座標"); r.right = ReadValue("長方形の右下隅のx座標"); r.bottom = ReadValue("長方形の右下隅のy座標"); Console.WriteLine(PtInRect(ref r, p) ? "内側" : "外側"); }
構造体のポインタを引数に受け取る場合
- .NETの構造体とアンマネージドな構造体ではメモリ確保の仕方が違うからMarshal.AllocCoTaskMem()を使う必要がある
SystemTime sysTime = new SystemTime();//StructLayoutで宣言した型 // Marshal.AllocCoTaskMem()で // 指定バイトのメモリ領域確保し、そのポインタを返す // Marshal.SizeOf()で、 // C#の構造体がメモリ上で何バイトかを取得する IntPtr sysTimePtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(sysTime)); // Win32API GetSystemTime()の呼び出し GetSystemTimeWin32(sysTimePtr); // sysTimePtrが示すメモリに格納された情報を、 // Marshal.PtrToStructure()で、C#の構造体にコピーする sysTime = (SystemTime)Marshal.PtrToStructure(sysTimePtr, sysTime.GetType()); // Marshal.AllocCoTaskMem()で確保したメモリを解放 Marshal.FreeCoTaskMem(sysTimePtr);
ツール
参照渡し
型
APIでの型名
(括弧内は対応するC言語の型)対応するC♯の型
(括弧内は.NET Frameworkでの型名)HANDLE (void*) System.IntPtr BYTE (unsigned char) byte (System.Byte?) SHORT (short) short (System.Int16?) WORD (unsigned short?) ushort (System.UInt16) INT (int)
LONG (long)int (System.Int32) UINT (unsigned int?)
DWORD, ULONG (unsigned long)uint (System.UInt32?) BOOL (long) bool (System.Boolean) CHAR (char) char (System.Char?) LPSTR (char*)
LPWSTR (wchar_t*?)System.Text.StringBuilder LPCSTR (const char*?)
LPCWSTR (const wchar_t*?)string (System.String) FLOAT? (float) float (System.Single) DOUBLE? (double) double (System.Double)
参考
- Win32 APIやDLL関数を呼び出すには?
- Win32 APIやDLL関数に文字列や文字列バッファを渡すには?
- Win32 APIやDLL関数に構造体を渡すには?