Tcl扩展:了解和使用ClientData

时间:2015-09-03 18:39:04

标签: c tcl

我正在努力更新旧软件(编写为针对Tcl / Tk 8.3构建),以便它针对更现代的发行版构建。我将此作为一个学习C和Tcl的机会,这两个项目在我开始时都没有编入过。所以,我非常新手。

对于我来说,了解Tcl API最令人困惑的事情之一是ClientData。 API中的许多函数都将其作为参数,但C扩展几乎从不使用它。我从this answer得到了很少使用全局定义的印象:

  

整个扩展ClientData适用于想要的扩展   发布自己的存根表...其他扩展可以构建。   这是一件非常难得的事情;如果你不这样做,请留空   想要它。

所以看起来它基本上是一个void参数,然后你需要在内部输入强制转换或句柄。但是代码中有一些地方我需要与ClientData进行交互(例如,对于空闲进程,如下所示):

typedef struct graph *Graph;

struct graph {
  int       num;
  int       hidden;
  int       needsRedraw;
...
};

flag drawNow(ClientData data) {
  Graph G;
  int g = (int) data;
  if (!(G = lookupGraph(g))) return TCL_OK;
  return drawGraph(G);
}

flag drawLater(Graph G) {
  if (!G->needsRedraw && !G->hidden) {
    G->needsRedraw = TRUE;
    Tcl_DoWhenIdle((Tcl_IdleProc *) drawNow, (ClientData) G->num);
  }
  return TCL_OK;
}

当我编译时,强制转换为整数会产生以下警告:

warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

我的主要困惑是(ClientData) G->num ---我不明白我要投的东西,因为我不知道ClientData是什么类型的东西。如果我查看Tcl来源,我找不到清晰度:

tclCompile.h:220:typedef ClientData (AuxDataDupProc)  (ClientData clientData);
tclInt.h:2520:typedef ClientData (TclFSGetCwdProc2)(ClientData clientData);
tclOOInt.h:73:typedef ClientData (TclOO_PmCDCloneProc)(ClientData clientData);

最后几点:在我开始对代码进行任何更新之前,存在这些编译器警告。该程序似乎适用于原始代码编译和运行的旧系统。所以,我不确定这个警告是否有任何意义......但它吓坏了我,只要我花时间学习代码并学习C和Tcl,我就希望能够深入了解它。 / p>

如果我没有提供足够的相关信息,请提前道歉。我很乐意提供更多,但这是我目前在一个好问题上的最佳努力。

1 个答案:

答案 0 :(得分:5)

一般来说,ClientData表示“Tcl 承诺它不会为你解释的指针”,并且几乎总是会在回调中传递给你的东西。将其视为void *(这是typedef的原因)。

您提到的答案是专门讨论Tcl_PkgRequireEx函数,其中ClientData内容用于传递对存根表的引用。你可以使用它来传递你自己的,但它非常复杂。这是一件非常罕见的事情;大多数人从不触及那些谜团。

一般来说,看到它与Tcl_CreateCommandTcl_CreateObjCommand相关时更为常见。在那里,clientData参数是一个指针,当调用创建的命令时,它将被传递回实现回调;对于表示类和类似事件的命令的命令,这是 great 。 Tcl将此用于程序之类的事情; proc命令使用clientData将指向正文脚本(和其他内容)的结构的指针传递给实现过程的C函数。如果您对Tk有一点了解,那么clientData会广泛用于将低级句柄传递给窗口结构。

使用Tcl_DoWhenIdle,它又是一个指针被移交给回调。回调函数的不同签名,当然,但基本的基本思想相同。

如果Tcl提供了C ++ API,它可能会做一些不同的事情,因为可以讨论指向该语言的实例方法的指针。但是Tcl的API是一个C API,所以一切都必须像这样工作。