C から関数を作成することはそれほど難しくありません。そのためには、操作を実行するコマンドの実装を作成し、その実装をコマンドとして正しい名前空間に登録する必要があります。(8.4 以前では、関数は別のインターフェイスで実行されていましたが、これは使用するのがかなり面倒でした。メカニズムは 8.5 で完全に見直されました。)
コマンドの実装
ここでは署名が定義されており、ignored
パラメーターは使用されていないことに注意してください。(コマンドをオブジェクトにバインドするようvoid *
なことをしたい場合には非常に便利ですが、追加を行うには必要ありません。)
static int AddCmd(ClientData ignored, Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]) {
double x, y, sum;
/* First, check number of arguments: command name is objv[0] always */
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "x y");
return TCL_ERROR;
}
/* Get our arguments as doubles */
if ( Tcl_GetDoubleFromObj(interp, objv[1], &x) != TCL_OK ||
Tcl_GetDoubleFromObj(interp, objv[2], &y) != TCL_OK) {
return TCL_ERROR;
}
/* Do the real operation */
sum = x + y;
/* Pass the result out */
Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sum));
return TCL_OK;
}
ここで値を割り当てているという事実について心配する必要はありません。Tcl には非常に高性能なカスタム メモリ マネージャーがあり、これにより操作が安価になります。
コマンド登録
これは通常、Tcl パッケージ定義の一部として登録されるか、アプリケーション全体の初期化の一部として呼び出される初期化関数内で行われます。Tcl_CreateInterp
手動で呼び出している場合は、直接行うこともできます。どちらを行うかは、Tcl とどのように統合しているかによって異なります。これは、それ自体が非常に大きなトピックです。そこで、初期化関数の作成方法を示します。これは通常、すべてのシナリオで適切なスタートです。
int Add_Init(Tcl_Interp *interp) {
/* Use the fully-qualified name */
Tcl_CreateObjCommand(interp, "::tcl::mathfunc::add", AddCmd, NULL, NULL);
return TCL_OK;
}
1 つ目は、最初の ( ) パラメータとして実装NULL
に渡される値です。2 つ目は、 (ここのようにアクションが必要ない場合は NULL)ClientData
を破棄するためのコールバックです。ClientData
これらすべてを C++ から実行することも非常に実用的ですが、Tcl はCライブラリであるため、それらは関数 (メソッドではなく、アダプターなしではなく) である必要があり、C リンケージが必要であることを覚えておいてください。
C (または C++) からプロシージャの本体を取得する最も簡単なメカニズムは、Tcl_Eval
実行する単純なスクリプトを使用することinfo body theCmdName
です。プロシージャーの実装は非常に複雑なので、それらへのインターフェースは純粋にスクリプト・レベルにあります (実際に賢明である以上に Tcl に巻き込まれない限り)。