我是Tcl脚本的新手,并希望使用C来嵌入Tcl代码。 这是我从网站上复制的代码,用于测试Tcl-C的工作情况。
test.c的
#include <stdio.h>
#include <tcl.h>
void main ()
{
Tcl_Interp *myinterp;
char *action = "set a [expr 5 * 8]; puts $a";
int status;
printf ("Your Program will run ... \n");
myinterp = Tcl_CreateInterp();
status = Tcl_Eval(myinterp,action);
printf ("Your Program has completed\n");
getch();
}
我正在使用MinGW来编译这个文件。
我已将 C:\ Tcl \ include 文件夹的内容复制到 C:\ MinGW \ include 文件夹中。
我的gcc命令用于编译:
gcc -o test.exe test.c
显示错误消息:
C:\Users\user\AppData\Local\Temp\ccEHJKCb.o:tcl_connection_test.c:(.text+0x23): undefined reference to `_imp__Tcl_CreateInterp'
C:\Users\user\AppData\Local\Temp\ccEHJKCb.o:tcl_connection_test.c:(.text+0x3d): undefined reference to `_imp__Tcl_Eval'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\ccEHJKCb.o: bad reloc address 0x20 in section `.eh_frame'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
我似乎在Tcl文件夹中没有任何libtcl文件。
Tcl版本是ActiveTcl 8.5.15.0.297577。
任何帮助都会非常感激。
答案 0 :(得分:1)
您的示例如何嵌入Tcl已过时,并且您在链接行(例如-ltcl85
)中缺少某些内容。如果您只是将-ltcl85
添加到链接行,它就应该开始工作了。
它不适用于您的情况,因为您安装了ActiveTcl的x64(64位版本),它提供x64 dll而不是32位dll。但标准mingw gcc仅适用于32位库。
所以要让它发挥作用:
gcc -o test.exe test.c -Lc:/tcl/lib -Ic:/tcl/include -ltcl86
set TCL_LIBRARY=c:\tcl\lib\tcl8.6
)但是对于更复杂的示例,您仍然需要初始化库并执行一些样板代码,因此请在调用Tcl_FindExecutable(argv[0]);
之前调用Tcl_CreateInterp()
,否则请调用一些命令(例如clock
可能只是没有按预期工作。)
有关详细信息,请查看http://www.tcl.tk/cgi-bin/tct/tip/66.html。另请参阅Tcl源代码分发和tclsh shell的源代码。
答案 1 :(得分:0)
你非常接近正确。
Tcler的Wiki有一些例子,其中一些非常令人困惑坦率,但这一个from this page是我最近发现的最好的。 (评论是我的。)
#include <stdlib.h>
#include <tcl.h>
int main (int argc, char *argv[]) {
Tcl_Interp *interp;
const char *script = "proc p1 a { puts $a }";
// Initialize the Tcl library; ***STRONGLY RECOMMENDED***
Tcl_FindExecutable(argv[0]);
// Create the interpreter, the execution context
interp = Tcl_CreateInterp();
// Initialise the interpreter
if (TCL_OK != Tcl_Init(interp)) {
fprintf(stderr, "Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
exit(EXIT_FAILURE);
}
// Define a procedure
Tcl_Eval(interp, script);
fprintf(stderr, "res 1: %s\n", Tcl_GetStringResult(interp));
// Check if the procedure exists
Tcl_Eval(interp, "puts [info commands p*]");
fprintf(stderr, "res 2: %s\n", Tcl_GetStringResult(interp));
// Call the procedure
Tcl_Eval(interp, "p1 abc");
fprintf(stderr, "res 3: %s\n", Tcl_GetStringResult(interp));
// We could use Tcl_DeleteInterpreter to clean up here, but why bother?
return EXIT_SUCCESS;
}
你还缺少什么?简单。在构建可执行文件时,您忘了告诉C编译器使用Tcl库;编译器(或者更严格地说,链接器)是一段愚蠢的代码。用于使链接器添加库的确切选项取决于您的系统配置,但可能是-ltcl
,-ltcl8.5
或-ltcl8.6
;这取决于文件名和所有我们无法在您的系统上无法准确检查的事情。这些名称确实符合一个简单的模式。
您可能还需要传递-L
选项以告知链接器有关其他库位置的信息。 (有一个等价的-I
用于告诉编译器在哪里找到包含文件,因此您不必将所有内容复制到一个巨大的无法管理的目录中。)
论证的顺序很重要。应在源文件后列出库:
gcc -o test.exe test.c -L/mingw/path/to/library/directory -ltcl86
(如果您使用旧的,不受支持的Tcl版本 - 为什么要这样做?! - 那么上面的代码将无效,因为Tcl_Eval
然后使用可写字符串但是很多年前这个问题已得到解决,升级到当前版本就是修复。)