我需要一个简单的 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
tl;dr
当编译一个程序时main
, you 不应该使用存根。相反,构建时无需USE_TCL_STUBS
and USE_TK_STUBS
定义和链接libtcl.so
and libtk.so
(好吧,不管它们附加了什么版本号)。由于 Unix 链接器的特殊性,您应该将 Tk 库放在 Tcl 库之前(并且您可能还需要手动链接其他库,例如 X 库;链接有时有点像魔术)。
背景说明
存根机制旨在允许 Tcl 扩展库使用 Tcl 的(和 Tk 的)C API,而不必链接到 Tcl 库本身。这意味着该库不知道加载它的过程中存在什么 Tcl 的确切版本,而只依赖于 Tcl API 的特定版本(Tcl 非常擅长管理长期 API 和 ABI 兼容性)。然而,这一切都取决于使用一种非常特殊的指针调用库初始化函数,该指针允许查找所有其他 API 函数。 (一旦以这种方式引导 Tcl,找到所有其他 API 就会变得容易得多。)当创建像您这样的应用程序时,您会遇到一个问题,因为没有现有的引导 Tcl 库实例供您的代码链接;它必须直接链接(事实上两者Tcl_Main
and Tk_Main
由于这个原因,它们是非存根函数)。
那些在家里阅读的人可能会认为这是 Tcl 重复了系统动态链接器所做的很多事情。你是对的。然而,系统动态链接器有很多方法可以做一些不太正确的事情(例如,它可以得到very当一个库有多个版本时会感到困惑)并且它在平台之间的功能存在微妙的差异。 Tcl 使用自己的机制,因为这使得它在任何地方都能准确地工作(对于 Tcl),使我们能够更好地控制长期 ABI 兼容性。
上述关于存根的规则有一个例外,那就是tclkit http://equi4.com/tclkit/,这是单个文件中的完整 Tcl 和 Tk 运行时(加上一个小型 NoSQL DB)。不过 tclkit 的引导代码非常复杂;你不想处理那些你不必处理的事情!如果您想要一个单文件 Tcl 运行时,您可以使用 tclkit(或其他几个能做几乎相同事情的系统之一)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)