マネージドコード(C#, VB.NET etc)で開発していると、プラットフォームのネイティブコードを使いたいことがある。
方法としては、以下の2つがある。
今回は「P/Invoke」を使用し、(1) 普通に実装する場合 (2) 関数宣言の出力ツールで実装する場合をそれぞれ説明していく。
目次
(1) 普通に実装する場合
サンプルとして、user32.dll の GetWindowText 関数を使ってみる。
この関数は、以下のように定義されている。
1 2 3 4 5 |
int GetWindowText( HWND hWnd, // ウィンドウまたはコントロールのハンドル LPTSTR lpString, // テキストバッファ int nMaxCount // コピーする最大文字数 ); |
(1-1) 関数宣言
規則に従って以下のように関数宣言する。
(※本記事では、規則の説明はしない。)
1 2 3 4 5 6 7 8 |
using System.Text; // String Builder using System.Runtime.InteropServices; // DLL Import class Test { [DllImport("user32.Dll", EntryPoint="GetWindowText")] public static extern int GetWindowText(int hwnd, StringBuilder lpString, int nMaxCount); } |
(1-2) 呼び出し
宣言した関数を使う。
1 2 3 4 5 6 7 8 |
private void button1_Click(object sender, EventArgs e) { int hwnd = (int)this.Handle; StringBuilder lpString = new StringBuilder(1024); Win32Api.GetWindowText(hwnd, lpString, lpString.Capacity); MessageBox.Show(lpString.ToString()); } |
(2) 関数宣言の出力ツールで実装する場合
(1) のようにシンプルだと良いが、呼び出す関数の引数が多かったり、宣言する関数の量が多いと、面倒になる。そこで、関数宣言のコードを自動生成してくれるツールを使用する。
(2-1) インストール
CLRInsideOut2008_01.exe ダウンロードする。
ダウンロードした CLRInsideOut2008_01.exe をダブルクリックするとインストーラーが起動するので、適当なディレクトリーへインストールする。
(2-2) 起動
インストールディレクトリへ移動し、winsiggen.exe をダブルクリックする。
「P/Invoke Interop Assistant version 1.0」を起動する。
今回は「SigImp Translate Snippet」タブを使用するので、クリック。
各タブの説明は以下のとおり。(Google翻訳)
- SigExp:管理されたバイナリをC ++ Reverse PInvokeシナリオに変換する。
- SigImp Search:よく使われる関数を検索し、それをマネージコードに変換する。
- SigImp Translate Snippet:Cコードを管理PInvoke署名に直接変換する。
(2-3) 関数宣言コードの生成
① Native Code Snippet に、使用する DLL 側の関数の定義をコピーする。
② Generate ボタンをクリックすると、
③ C# に記載する関数宣言が生成される。これをコピーし、ソースコードに貼り付ける。
ちなみに、自作したDLLの場合は、DLL 名を判断できないため「Unknown」と出力されるので、適切なDLL名に置き換える必要がある。
(2-4) 構造体のコード生成
関数宣言コードの時と同じように、「Native Code Snippet」に構造体を貼り付けると、出力できる。