在 C 程序中使用 tcl 和 tk 存根 [英] Use tcl and tk stubs in C program

查看:28
本文介绍了在 C 程序中使用 tcl 和 tk 存根的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need a simple C program which creates tcl interpreter, initializes tcl and tk and then loads a given tcl/tk script. I want to use tcl and tk stubs (to ensure that the program will run on the computer with different version of tcl/tk). I will use this program instead of running wish (because I have portability problems).

#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 上).程序编译没有错误,但随后因分段错误而停止.

I tried to compile (on GNU/Linux) with the following command. Program compiles without errors, but then stop with segmentation fault.

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 的程序时,不应该使用存根.相反,在没有 USE_TCL_STUBSUSE_TK_STUBS 定义和链接的情况下构建 libtcl.solibtk.so(好吧,附有任何版本号).由于 Unix 链接器的特殊性,您应该将 Tk 库放在 Tcl 库之前(并且您可能还需要手动链接其他库,例如 X 库;链接有时有点像黑色艺术).

tl;dr

When compiling a program with a main, you shouldn't use stubs. Instead, build without the USE_TCL_STUBS and USE_TK_STUBS defines and link against libtcl.so and libtk.so (well, with whatever version number's been attached to them). Because of peculiarities in the Unix linker, you should put the Tk library before the Tcl library (and you might also need to manually link against other libs too, such as the X library; linking is occasionally a bit of a black art).

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

The stubs mechanism is intended to allow a Tcl extension library to use Tcl's (and Tk's) C API without having to be linked against the Tcl library itself. This means that the library is agnostic to what exact version of Tcl is present in the process loading it, and instead just depends on a particular version of the Tcl API (Tcl's pretty good at managing long term API and ABI compatibility). However, this all depends on the library initialization function getting called with a very particular kind of pointer which allows all the other API functions to be looked up. (Once Tcl's been bootstrapped this way, it becomes much easier to find all the other APIs.) When creating an application like you're doing, you run into a problem in that there's no existing bootstrapped Tcl library instance for your code to link against; it has to be linked directly (and in fact both Tcl_Main and Tk_Main are non-stubbed functions for this exact reason).

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

Those of you reading along at home might think that this is Tcl repeating a lot of what the system dynamic linker does. You'd be right. However the system dynamic linker has a number of ways it can do things that don't work quite right (e.g., it can get very confused when there are multiple versions of a library about) and it varies subtly in its capabilities between platforms. Tcl uses its own mechanism because that makes it work precisely right (for Tcl) everywhere, giving us much better control over long-term ABI compatibility.

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

There is an exception to the above rule about stubs, and that is tclkit, which is a full Tcl and Tk runtime (plus a small NoSQL DB) in a single file. The bootstrapping code for tclkit is horrendously complex though; you don't want to have to deal with that sort of thing you don't have to! If you want a single-file Tcl runtime, you use tclkit (or one of the few other systems that do pretty much equivalent things).

这篇关于在 C 程序中使用 tcl 和 tk 存根的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆