1

我使用 TCL 8.4,对于该版本,我需要使用 TCL 库函数将新的数学函数添加到 TCL 解释器中,特别是Tcl_CreateMathFunc. 但我找不到一个如何做到这一点的例子。请你为我写一个非常简单的例子,假设在 C 代码中你有一个Tcl_Interp *interp你应该添加一个数学函数(比如,一个将两个双数相乘的函数)。

4

2 回答 2

3

我曾经为 Tcl 做过一些随机数生成器的替代实现,您可以在git 存储库中查看一些示例。generic 中的文件为每个 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;
 }
于 2012-06-16T13:07:55.053 回答
2

请注意,这是一个不太可能无限期存在的 API(原因包括其怪异的类型、不灵活的参数处理以及无法从 Tcl 本身轻松使用它)。但是,以下是如何在add(x,y)两个参数都为doubles 的情况下执行操作:

登记

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——只允许在注册/声明中——使事情变得相当复杂,而且你真的被固定的参数数量所困扰。)

于 2012-06-16T18:06:01.253 回答