なでしこのDLLに含まれる(なでしこから呼ばれる)関数はそんなに多くなく、
・ImportNakoFunction
・PluginInfo
・PluginVersion
・PluginRequire
・PluginInit
・PluginFin
の6つです。この内、自分でせっせといじる必要があるのは
・ImportNakoFunction
で、この中で自分の作成した関数(命令)を登録します。 たとえば、なでしこから
DLLに渡ってくる引数のチェックをする関数を作ったとします。
------ここから------
void _disp_nakovar(PHiValue pvar)
{
if (pvar != NULL)
{
switch (pvar->VType)
{
case varNil :
DBGPRINTF("Var is Nil(%d)\n", pvar->VType);
break;
case varInt :
DBGPRINTF("Var is Int(%d)\n", pvar->VType);
break;
case varStr :
DBGPRINTF("Var is Str(%d)\n", pvar->VType);
break;
default :
DBGPRINTF("Var is Unknown(%d)\n", pvar->VType);
break;
}
}
}
------ここまで------
あ、デバッグ用に作ったのでDBGPRINTF()とかなってますが、
中身はprintf()です。 PHiValuはなでしこの変数を格納するための
構造体(へのポインタ)で、これに変数の種類とかいろいろ書いて
ありあす。途中省略してますが、この構造体の中身みれば、
大体のことが分かります(…って言うか、なでしこからDLLに
渡される情報はこの構造体が全てです(^^; )。
このままではなでしこに登録できませんので、なでしこの命令と
して登録できる形の関数を書く必要があります。
------ここから------
PHiValue __stdcall dnako_varchk(DWORD h)
{
PHiValue arg1 = 0;
PHiValue ret = 0;
NAKO_FUNCS *pfnako = _get_nako_funcs();
DBGPRINTF("Enter -- %s()\n", __FUNCTION__);
arg1 = pfnako->nako_getFuncArg(h, 0);
ret = pfnako->nako_var_new(NULL);
DBGVARCHK(arg1);
return(ret);
}
------ここまで------
なでしこに登録する命令は常にこの形になっています。
PHiValue __stdcall dnako_varchk(DWORD h)
は、戻り値がPHiValue、Windowsの関数コール規約__stdcall、関数名が
dnako_varchk(これはユーザーが任意に名前つけられます)、引数は
DWORD型のh一つだけとなります。
命令の引数から実際の変数を取得する場合は
・pfnako->nako_getFuncArg(h, 0)
を使用します。pfnakoは関数セットを構造体として持っていて、
そこへのポインタです。この関数を実行することで、引数のh
から、PHiValueの変数を引っ張ってこれる仕組みです。
命令の引数が複数ある場合は、
arg1 = pfnako->nako_getFuncArg(h, 0);
arg2 = pfnako->nako_getFuncArg(h, 1);
arg3 = pfnako->nako_getFuncArg(h, 2);
と、引数分実行すれば順番に取得できます。つまりnako_getFuncArg()
の第二引数は、変数のリストだか配列だかのインデックスってこと
ですね。先頭のインデックスは0です。
こうやって取得したarg1はPHiValue型ですので、必要に応じてここから
整数や文字列を取り出します。pfnakoの中に、
・nako_var2int() /*PHiValueからint型の値取り出し*/
・nako_var2str() /*PHiValueから文字列取り出し*/
などがあるので、必要に応じて使用します。
最後に、この関数はデバッグ用だったので、戻り値は特に必要なかった
ですが、実際に必要な場合には、
・ret = pfnako->nako_var_new(NULL);
でPHiValue型の空の変数を作成した後、
・nako_int2var()
などを使用して、PHiValue型に実際をセットし、これをなでしこに返します。
すると、それがなでしこ命令を実行した際の戻り値になるわけですね~♪
最後はこのdnako_varchk()をなでしこに登録します。上でも書きましたが
登録するのは、
ImportNakoFunction()の中身でやります。
------ここから------
NAKO_API(void) ImportNakoFunction(void)
{
NAKO_FUNCS *pfnako = _get_nako_funcs();
DBGPRINTF("Enter -- ImportNakoFunction()\n");
pfnako->nako_addFunction("DLL引数ダンプ", "A", dnako_varchk, 0);
}
------ここまで------
・pfnako->nako_addFunction("DLL引数ダンプ", "A", dnako_varchk, 0);
が実際に登録してる場所で、"DLL引数ダンプ"はなでしこの命令名、
"A"がその時の引数、 "dnako_varchk"が上で作ったCの関数名です。
最後の0は…分かりませんヾ(;´▽`A``。サンプルに0が設定されてたので
0にしてあります…。
なでしこ命令の引数ですが、"A"と書いた部分に"A,B"と書いておけば
引数が2つってことになります。またここに"Aの"とか書いておけば、
なでしこ命令としても「AのDLL引数ダンプ」みたいに書けます。上の
場合は
・DLL引数ダンプ(A)
と、ちょっとC言語っぽくなりますが、今回は引数が多めの命令も
ありますので、これで統一します。