tcl库:如何使用tcl_eval()为c-code tcl命令扩展设置返回结果?

时间:2017-10-19 19:07:15

标签: c tcl

假设我实现了一个用c-code编写的新tcl命令,我使用Tcl_CreateObjCommand注册,在这个c代码中我调用Tcl_Eval来eval一个包含代码的字符串来创建一个关联数组并存储它在变量tmp中。如何将使用Tcl_eval()创建的tmp变量设置为c函数的返回结果对象?

示例:

int MyCommand(
    ClientData   clientData,
    Tcl_Interp*  interp,
    int          argc,
    char*        argv[])
{

     int rc = Tcl_Eval(interp, 
       "array set tmp [list {key1} {value1} {key2} {value2}]");
     if (rc != TCL_OK) {
         return rc;
     }

     //???
     Tcl_SetObjResult(interp, ?? tmp variable from eval??);
     return TCL_OK;
}

当我使用上面的C-extension运行Tcl解释器时,我希望看到这个结果:

TCL> set x [MyCommand]

TCL> puts "$x(key1)"
value1   # Currently an Error and not set

TCL> puts "$x(key2)"
value2   # Currently and Error and not set

以某种方式工作。只是不是我想要它的方式。例如,如果我输入:

TCL> set x [MyCommand]

TCL> puts "$tmp(key1)"
value1   # Its Works!  Except, I didn't want to set a global variable tmp

TCL> puts "$tmp(key2)"
value2  # Its Works!  Except, I didn't want to set a global variable tmp

(也许它是一个"功能"设置tmp而不是??)无论如何,我仍然希望它通过使用proc" return"返回值来正确工作。机构。

从c-command-extension的Tcl_Eval内部调用Tcl_Eval()应该是合法的,因为" Tcl库"对于tcl_eval,使用嵌套调用来评估其他命令是合法的。我只是不知道如何将对象结果从Tcl_Eval复制到"返回" c扩展程序的对象。

2 个答案:

答案 0 :(得分:2)

我在这里看到两个问题。您不能将命令的返回值设置为数组的值,因为数组不是值。数组是由字符串索引的变量集合。这是一个常见的误解。您可以返回数组元素的值。如果您想要一个适当的Tcl值的键/值映射,请考虑使用字典。字典是值,可以作为命令的值返回。

第二个问题为什么使用Tcl_Eval()来创建数组。使用Tcl_SetVar()或其中一个变体来构建数组要简单得多。

答案 1 :(得分:2)

设置数组的推荐方法(假设您首先使用char*值)是使用对Tcl_SetVar2的调用(之所以这样命名是因为它将变量名称作为两部分)。

Tcl_SetVar2(interp, "tmp", "key1", "value1", 0);
Tcl_SetVar2(interp, "tmp", "key2", "value2", 0);

惯用法,您将使用作为参数传入C语言命令实现的名称作为参数,以便调用者可以告诉您要写入的变量,并且您也想检查结果:< / p>

int MyCommand(
    ClientData   clientData,
    Tcl_Interp*  interp,
    int          argc,
    char*        argv[])
{
    // Missing: check # of arguments

    if (Tcl_SetVar2(interp, argv[1], "key1", "value1", 0) == NULL)
        return TCL_ERROR;
    if (Tcl_SetVar2(interp, argv[1], "key2", "value2", 0) == NULL)
        return TCL_ERROR;
    return TCL_OK;
}

然后你会这样称呼:

MyCommand x
# It has no meaningful result.

puts $x(key1)
puts $x(key2)