2010/08/12

構造体を使用したネイティブコード関数呼び出し

DLLが提供するネイティブコード関数の中には、複数の値からなるバイト列である「構造体」を使用する物も少なくありません。
ここでは、構造体を利用したネイティブコード関数呼び出しの方法を説明します。

下記は、構造体を利用したネイティブコード関数呼び出しの一例です。

var Point=new Struct({
 x:Int,
 y:Int,
});
var GetCursorPos=user32.proc("GetCursorPos",[Point],Int);
try{
 var point=Point.alloc();
 GetCursorPos(point);
 println([point.x,point.y]);
 println(Hex.encode(point));
}finally{
 free(point);
}

最初に「new Struct()」で構造体オブジェクトを生成して、変数に代入しています。引数には、構造体のフィールド名と値の型を表すオブジェクトのペアを列挙したオブジェクトを指定します。フィールド定義は、構造体内での並び順の通りに並べる必要があります。
ライブラリオブジェクトのproc()によるラッパー関数定義で、引数の型を指定する箇所に構造体オブジェクトを格納した変数名を記述すれば、その構造体へのポインタを引数として受取ることを指定できます。

tryブロック内が、構造体オブジェクトを利用した関数呼び出しを行う部分です。
構造体のバッファは、UIntなどのバッファの時と同じように、「alloc()」メソッドで確保します。
この返り値を引数にしてGetCursorPos()を呼び出すことにより、確保したバッファ内に値が書き込まれます。
「point.x」や「point.y」のように、構造体定義で指定したフィールド名と同じ名前のプロパティで、バッファ内の当該フィールドの値を取得できます。また、「point.x=100」のようにすれば、フィールドの値を書き換えることも可能です。
なお、「Hex.encode()」は、ポインタオブジェクトが確保しているバイト列を2桁区切りの16進数文字列として返すメソッドです。ポインタを利用した関数の動作確認をしたい場合などに役立ちます。

最後に、確保したバッファを解放するたに、finallyブロック内で「free()」関数を実行しています。使用する関数によっては、すぐにバッファを解放してはならない場合などもありますので、関数のドキュメントなどをよく確認してください。

0 件のコメント:

コメントを投稿