向标准TCL添加数学运算

时间:2012-06-11 18:10:46

标签: runtime tcl

如你所知TCL有一些数学函数,如 sin cos hypot ,在 expr中调用()括号的命令如下:

puts [expr sin(1.57)]

现在我如何使用TCL library functions添加一个函数,以便以完全相同的方式调用它,并且正在执行某些 proc 定义的操作。

我想澄清一下我的问题。假设有一个proc(字符串)如下:

proc add { a b } { return [expr $a+$b] } ;# string of a proc

我的C ++代码中也有一个TCL解释器。现在我想得到一个proc 的字符串,并且运行时将一个名为 add 的函数注册到tcl::mathfunc namespace(我想我应该使用Tcl_CreateObjCommand)所以我可以打电话给以下人员:

puts [expr add(1.57, 1.43)]

如何做到这一点。你能写一个简单的例子吗?我在TCL文档和书籍中找不到任何描述this command用法的例子。

1 个答案:

答案 0 :(得分:3)

从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;
}

第一个NULL是作为第一个(ClientData)参数传递给实现的值。第二个是回调处理ClientData(如果不需要任何操作,则返回NULL,如此处所示)。

从C ++完成所有这些操作也非常实用,但请记住,Tcl是 C 库,因此它们必须是函数(不是方法,不是没有适配器),而且它们需要C链接。


要从C(或C ++)获取过程的主体,到目前为止最简单的机制是使用Tcl_Eval运行一个简单的脚本来运行info body theCmdName。程序实现非常复杂,因此它们的接口纯粹是在脚本级别(除非你真的用Tcl纠缠自己,而不是非常明智)。