在C程序中使用tcl和tk存根

时间:2012-06-15 08:13:25

标签: c tcl

我需要一个简单的C程序来创建tcl解释器,初始化tcl和tk然后加载给定的tcl / tk脚本。我想使用tcl和tk存根(以确保程序将在具有不同版本的tcl / tk的计算机上运行)。我将使用此程序而不是运行wish(因为我有可移植性问题)。

#include <stdio.h>
#include <stdlib.h>
#include <tcl.h>
#include <tk.h>

int AppInit(Tcl_Interp *interp) {
  if(Tcl_Init(interp) == TCL_ERROR) return TCL_ERROR;
  if(Tk_Init(interp) == TCL_ERROR) return TCL_ERROR;
  Tcl_EvalFile(interp,"myscript.tcl");
  return TCL_OK;
}

int main(int argc, char *argv[]) {
  Tk_Main(argc, argv, AppInit);
  return 0;
}

我尝试使用以下命令编译(在GNU / Linux上)。程序编译没有错误,但随后停止分段错误。

gcc -I/usr/include/tcl8.5 -DUSE_TCL_STUBS -DUSE_TK_STUBS -o main.exe ../main.c /usr/lib/libtclstub.a /usr/lib/libtkstub.a

1 个答案:

答案 0 :(得分:3)

TL;博士

使用main编译程序时,不应使用存根。相反,在没有USE_TCL_STUBSUSE_TK_STUBS的情况下进行构建并定义并链接libtcl.solibtk.so(以及附加到它们的任何版本号)。由于Unix链接器的特殊性,你应该将Tk库放在Tcl库之前(你可能还需要手动链接其他库,比如X库;链接有时候是一种黑色艺术)。 / p>

背景说明

存根机制旨在允许Tcl扩展库使用Tcl(和Tk)的C API,而不必与Tcl库本身链接。这意味着该库与加载它的过程中存在的Tcl的确切版本无关,而是仅取决于特定版本的Tcl API(Tcl非常擅长管理长期API和ABI兼容性)。但是,这完全取决于使用非常特殊的指针调用库初始化函数,该指针允许查找所有其他API函数。 (一旦Tcl以这种方式被引导,找到所有其他API变得更加容易。)在创建像你正在做的应用程序时,你遇到了一个问题,因为没有现有的自举Tcl库实例供你的代码链接;它必须直接链接(实际上,Tcl_MainTk_Main都是非存根函数,因为这个原因。)

你们在家里读书的人可能会认为这是Tcl重复系统动态链接器所做的很多事情。你是对的。然而,系统动态链接器有许多方法可以做一些不能正常工作的事情(例如,当有多个版本的库时,它可能会让非常混淆)并且它会巧妙地变化在平台之间的能力。 Tcl使用自己的机制,因为它使得它在任何地方都能正确地工作(对于Tcl),使我们能够更好地控制长期的ABI兼容性。

关于存根的上述规则有一个例外,那就是tclkit,它是一个完整的Tcl和Tk运行时(加上一个小的NoSQL DB)在一个文件中。但是,tclkit的引导代码非常复杂;你不想要处理那种你没有的东西!如果你想要一个单文件的Tcl运行时,你可以使用tclkit(或其他几个做同等事情的系统之一)。