最終更新:2021-10-09 (土) 07:53:26 (928d)  

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 APIDLL関数の宣言では、関数の実体が外部にあることを表すextern修飾子と、静的なメンバであることを表すstatic修飾子を必ず指定する。なお、ここではpublicprivateなどのアクセス修飾子は省略したが、必要であれば指定することもできる。
[DllImport("kernel32.dll")]
extern static bool Beep(uint dwFreq, uint dwDuration);

フィールド

BestFitMapping?

CallingConvention

CharSet

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);

ツール

参照渡し

参考