前回は引数を取得する方法を、説明だけしたので、今回はそれを元に、プラグインを作っていきます。
今回作成するプラグインのコードは、GitHubにまとめて公開してあります:HSP3向けプラグイン「getvarinfo」リポジトリ
これを見ておく必要はありませんが、何かの参考になれば幸いです。
今回は GetVarinfo 命令を作成します。
使い方はこんな感じ。
// GetVarinfo のテスト a = 32 ; GetVarinfo 変数, 情報を格納する配列 GetVarinfo a, info mes "要素数[0] = " + info(0) mes "要素数[1] = " + info(1) mes "要素数[2] = " + info(2) mes "要素数[3] = " + info(3) mes "要素数[4] = " + info(4) mes "変数型 = " + info(5) mes "モード = " + info(6) mes "ポインタ = " + info(7) stop
プラグインじゃなくてもいい気がしますが、そこら辺は突っ込んではいけません。( ほら、モードとか取得できないでしょ! )
length()とvarptr()が合体して、+αされた感じです。
プラグイン本体の内容はほとんど一回目と同じなので、省略します。
GetVarinfoを処理する部分だけ書きましょう。
まず、変数を両方受け取ります。変数は code_getva()、配列変数は code_getpval() でしたね。
このあたりについては第2回を思い出しておいてください。
次に、変数の情報を格納したいので、pvInfo を初期化します。
HSP同様、dim命令を使いますが、プラグインでは exinfo->HspFunc_dim() です。
引数の数が多いので、複数行に分けて書くこともあります。
引数の意味は:( 対象の変数のPVal*, 初期化後の新しい型, len[0], len[1], len[2] ... ); です。
HSPVAR_FLAG_STR( str )にするときは、sdim の第一引数を len[0] のところに書きます。
ここで出てきた MAX_VARINFO は、見ての通り定数です。
dllmain.h で、次のように定義を書いておきます。
変数情報の配列の添字番号です。VARINFO_MAX はちょうど、配列の要素数となります。
GetVarinfo 命令が取得する情報のほとんどは PVal 構造体のメンバからすぐに取り出せますが、ポインタ(varptr)を取得するためには HspVarProc 構造体が持つ GetPtr 関数を呼ぶ必要があります。
配列の長さは PVal::len を、型は PVal::flag に、モードは PVal::mode にあります。
もし与えられた変数(pvTarget)が配列でなければ、そのポインタは PVal::pt にあります。しかし GetVarinfo に配列の中の要素 a(i) が与えられたときは、そのポインタ(varptr)は GetPtr を使って求めなければいけません。
さて、最後に pvInfo が指す変数に、変数の情報を書き込んでいきます。
この変数は int 型だと分かっている(というか int 型に変換する)ので、HspVarProc がなくても扱うことができますが、HspVarProc を介したほうが礼儀正しいので使っておきます。
ループの中にある「phvpint->GetPtr(pvInfo)」は、pvInfo が指す変数の各要素へのポインタを表しています。
int 型の HspVarProc の GetPtr は PVal::offset (APTR) が表す添字に対応する要素のポインタを取得するので、PVal::offset を書き換えてから呼ぶことで、配列の要素のポインタを取り出すことができるのです。
Set 関数は代入を行う関数です。
(本当にただ代入するだけなので説明することがない。)
int *p;
int *q;
phvpint->Set(pval, p, q)
//↓int 型の場合はこういう意味
*p = *q;
これで、GetVarinfo 命令の完成です!
上記のプラグインは、前回と同じ方法でコンパイルできます。
次に、このプラグインのために、.as ファイルを書きます。
enum の定数も、ユーザのために定義しておいた方が親切でしょう (たまにこれを書いてない面倒な(以下愚痴ry))。
// GetVarinfo.hpi - public header #ifndef IG_GETVARINFO_HPI_AS #define IG_GETVARINFO_HPI_AS #regcmd "_hsp3hpi_init@4", "getvarinfo.hpi" #cmd GetVarinfo 0x000 // 定数 #enum global VARINFO_LEN0 = 0 #enum global VARINFO_LEN1 #enum global VARINFO_LEN2 #enum global VARINFO_LEN3 #enum global VARINFO_LEN4 #enum global VARINFO_FLAG #enum global VARINFO_MODE #enum global VARINFO_PTR #enum global VARINFO_MAX //######## サンプル・スクリプト ######## #if 1 // 本当はもっと入念にテストしてください (>_<; a = 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 GetVarinfo a(1), info mes "len1 : "+ length(a) +"\t: "+ info(VARINFO_LEN1) mes "len2 : "+ length2(a) +"\t: "+ info(VARINFO_LEN2) mes "len3 : "+ length3(a) +"\t: "+ info(VARINFO_LEN3) mes "len4 : "+ length4(a) +"\t: "+ info(VARINFO_LEN4) mes "ptr : "+ varptr(a(1)) +"\t: "+ info(VARINFO_PTR) mes "flag : "+ vartype(a(1)) +"\t: "+ info(VARINFO_FLAG) mes "mode : "+ info(VARINFO_MODE) stop #endif
※BCCの人は _hsp3hpi_init@4 を hsp3hpi_init に変えます。
今回はサンプルも書いておきました。サンプルはこのように、#if でサンプル部分を囲っておくのが通例です。
プラグインを実際に使うときは、#if の値を 0 に変えて、サンプルが実行されないようにします。
これで、変数の受け取り、初期化、代入ができるようになりました!
HspVarProc::GetPtr() のポインタを使って、値の取得も出来ますね。
では、また次回。
by 上大