使用TCL_CreateMathFunc在TCL中定义新的数学函数

使用TCL_CreateMathFunc在TCL中定义新的数学函数,math,tcl,Math,Tcl,我使用TCL 8.4,对于该版本,我需要通过使用TCL库函数,特别是TCL_CreateMathFunc,向TCL解释器添加一个新的数学函数。但我找不到一个例子来说明如何做到这一点。请你给我写一个非常简单的例子,假设在C代码中有一个Tcl_Interp*Interp,你应该在其中添加一个数学函数,比如说,一个将两个双倍数相乘的函数。我曾经为Tcl做过一些随机数生成器的替代实现,你可以看看下面的一些例子。generic中的文件为每个PRNG实现tcl命令和tcl数学函数 例如,在Mersenne

我使用TCL 8.4,对于该版本,我需要通过使用TCL库函数,特别是TCL_CreateMathFunc,向TCL解释器添加一个新的数学函数。但我找不到一个例子来说明如何做到这一点。请你给我写一个非常简单的例子,假设在C代码中有一个Tcl_Interp*Interp,你应该在其中添加一个数学函数,比如说,一个将两个双倍数相乘的函数。

我曾经为Tcl做过一些随机数生成器的替代实现,你可以看看下面的一些例子。generic中的文件为每个PRNG实现tcl命令和tcl数学函数

例如,在Mersenne Twister实现中,在package init函数中,我们通过声明

Tcl_CreateMathFunc(interp, "mt_rand", 1, (Tcl_ValueType *)NULL, RandProc, (ClientData)state);
这为我们注册了C函数RandProc。在本例中,该函数不接受任何参数,但使用了等效的sr,并显示了如何处理单个参数

/*
 * 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;
 }

我曾经为Tcl做过一些随机数生成器的替代实现,您可以在下面的示例中查看。generic中的文件为每个PRNG实现tcl命令和tcl数学函数

例如,在Mersenne Twister实现中,在package init函数中,我们通过声明

Tcl_CreateMathFunc(interp, "mt_rand", 1, (Tcl_ValueType *)NULL, RandProc, (ClientData)state);
这为我们注册了C函数RandProc。在本例中,该函数不接受任何参数,但使用了等效的sr,并显示了如何处理单个参数

/*
 * 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本身轻松使用它。但是,以下是如何在两个参数都是双参数的情况下执行addx,y:

登记 Tcl_ValueType类型[2]={Tcl_DOUBLE,Tcl_DOUBLE}; Tcl_CreateMathFuncinterp,add,2,types,AddFunc,NULL; 实施 忽略静态int AddFuncClientData,Tcl_Interp*Interp, Tcl_值*参数,Tcl_值*结果{ double x=args[0]。double值; 双y=args[1]。双值; 结果tr->doubleValue=x+y; 结果tr->type=TCL\u-DOUBLE; 返回TCL_OK; }
请注意,由于此API始终使用固定数量的函数参数,并且参数类型转换为您处理,因此您编写的代码可能非常短。使用TCL_将其编写为灵活的类型(仅在注册/声明中允许),这会使事情变得更加复杂,并且您确实需要固定的参数计数。

请注意,这是一个API,由于其怪异的类型、不灵活的参数处理、,以及Tcl本身无法轻松使用它。但是,以下是如何在两个参数都是双参数的情况下执行addx,y:

登记 Tcl_ValueType类型[2]={Tcl_DOUBLE,Tcl_DOUBLE}; Tcl_CreateMathFuncinterp,add,2,types,AddFunc,NULL; 实施 忽略静态int AddFuncClientData,Tcl_Interp*Interp, Tcl_值*参数,Tcl_值*结果{ double x=args[0]。double值; 双y=args[1]。双值; 结果tr->doubleValue=x+y; 结果tr->type=TCL\u-DOUBLE; 返回TCL_OK; } 请注意,由于此API始终使用固定数量的函数参数,并且参数类型转换为您处理,因此您编写的代码可能非常短。使用TCL_将其编写为灵活的类型(仅允许在注册/声明中使用),这会使事情变得非常复杂,并且您实际上需要固定的参数计数