私は TCL 8.4 を使用しており、そのバージョンでは、TCL ライブラリ関数を使用して新しい数学関数を TCL インタープリターに追加する必要がありますTcl_CreateMathFunc
。しかし、それがどのように行われるかを示す例は 1 つも見つかりませんでした。Tcl_Interp *interp
Cコードに数学関数(たとえば、2つの倍数を乗算する関数)を追加する必要があると仮定して、非常に簡単な例を書いていただけませんか。
2 に答える
私はかつて、Tcl 用の乱数ジェネレーターの代替実装をいくつか行ったことがあり、git リポジトリーでいくつかの例を見ることができます。ジェネリックのファイルは、PRNG ごとに tcl コマンドと tcl 数学関数の両方を実装します。
たとえば、Mersenne Twister の実装では、パッケージの init 関数で、次のように宣言して新しい関数をインタープリターに追加します。
Tcl_CreateMathFunc(interp, "mt_rand", 1, (Tcl_ValueType *)NULL, RandProc, (ClientData)state);
これにより、C 関数 RandProc が登録されます。この場合、関数は引数を取りませんが、同等のシード (srand) は単一のパラメーターを処理する方法を示しています。
/*
* A Tcl math function that implements rand() using the Mersenne Twister
* Pseudo-random number generator.
*/
static int
RandProc(ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr)
{
State * state = (State *)clientData;
if (! (state->flags & Initialized)) {
unsigned long seed;
/* This is based upon the standard Tcl rand() initializer */
seed = time(NULL) + ((long)Tcl_GetCurrentThread()<<12);
InitState(state, seed);
}
resultPtr->type = TCL_DOUBLE;
resultPtr->doubleValue = RandomDouble(state);
return TCL_OK;
}
これは無期限に存続する可能性が非常に低い API であることに注意してください (奇妙な型、柔軟性のない引数処理、Tcl 自体から簡単に使用できないなどの理由により)。ただし、add(x,y)
両方の引数をdouble
s にして an を実行する方法は次のとおりです。
登録
Tcl_ValueType types[2] = { TCL_DOUBLE, TCL_DOUBLE };
Tcl_CreateMathFunc(interp, "add", 2, types, AddFunc, NULL);
実装
static int AddFunc(ClientData ignored, Tcl_Interp *interp,
Tcl_Value *args, Tcl_Value *resultPtr) {
double x = args[0].doubleValue;
double y = args[1].doubleValue;
resultPtr->doubleValue = x + y;
resultPtr->type = TCL_DOUBLE;
return TCL_OK;
}
この API は常に関数への固定数の引数を使用して動作するため (引数の型変換は自動的に処理されるため)、作成するコードはかなり短くなる可能性があることに注意してください。(登録/宣言でのみ許可されているタイプフレキシブルになるように書くと、TCL_EITHER
物事がかなり複雑になり、実際には固定された引数の数で立ち往生しています。)