【问题标题】:tcl library: how to use tcl_eval() to set return result for c-code tcl command extension?tcl 库:如何使用 tcl_eval() 设置 c 代码 tcl 命令扩展的返回结果?
【发布时间】:2018-03-31 22:02:56
【问题描述】:

假设我实现了一个用 c 代码编写的新 tcl 命令,我使用 Tcl_CreateObjCommand 注册了该命令,在这个 c 代码内部我调用 Tcl_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 扩展运行 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“返回”机制返回值来以正确的方式工作。

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

【问题讨论】:

    标签: c tcl


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

      通常,您可以使用作为参数传递给您的 C 命令实现的名称作为参数,以便调用者可以告诉您要写入哪个变量,并且您也想检查结果:

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多