Home -> HSP講座 -> HPI編 No.3

変数を受け取ろう

前回は引数を取得する方法を、説明だけしたので、今回はそれを元に、プラグインを作っていきます。

今回作成するプラグインのコードは、GitHubにまとめて公開してあります:HSP3向けプラグイン「getvarinfo」リポジトリ
これを見ておく必要はありませんが、何かの参考になれば幸いです。


作成する命令: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の引数を取得

プラグイン本体の内容はほとんど一回目と同じなので、省略します。
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 上大

第二章へ   第四章へ