2014-07-26 53 views
0

我是Tcl脚本新手,想用C嵌入Tcl代码。 这是我从网站上复制的代码,用于测试Tcl-C的工作。Tcl解释器在使用gcc编译时未定义的引用错误

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的\包括夹入C:\ MinGW的\包括文件夹为好。

我对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

好老株/非存根问题.. –

+0

我不知道那经典的问题是什么 – theClassicFreak

回答

1

您的示例如何嵌入Tcl已过时,并且您在链接行中缺少某些内容(例如,-ltcl85)。如果您只需将-ltcl85添加到您的链接中,就应该开始工作。

由于您安装了ActiveTcl的x64(64位版本),它提供了x64 dll,而不是32位,所以它不起作用。但标准的mingw gcc只适用于32位库。

因此,要得到这个工作:

  1. 下载32位ActiveTcl分布
  2. gcc -o test.exe test.c -Lc:/tcl/lib -Ic:/tcl/include -ltcl86
  3. 编译代码调整你的路径,以便在C:\ TCL \ BIN \ tcl86.dll在PATH被发现,同时也要确保Tcl的认定其LIBDIR(01​​)
  4. 运行程序

但是对于更复杂的例子,您仍然需要初始化库并做一些样板代码,所以请在拨打Tcl_CreateInterp()之前拨打Tcl_FindExecutable(argv[0]);,否则请拨打一些命令(例如: clock可能无法按预期工作)。

查看http://www.tcl.tk/cgi-bin/tct/tip/66.html了解更多详情。还可以看看Tcl源代码分发和tclsh shell的源代码。

+0

好吧,我升级到Tcl 8.6并尝试了以下gcc命令,但所有这些命令都失败了。 'GCC-LC:\ Tcl的\ lib中-o test.exe的test.c' 'GCC -ltcl -LC:\ Tcl的\ lib中-o test.exe的test.c' 'GCC -ltcl8.6 -LC:\ Tcl的\ lib中-o test.exe的test.c' 'GCC -ltcl8.6 -o test.exe的test.c' 'GCC -ltcl -o test.exe的test.c' 这真是难过;这真是伤心。 – theClassicFreak

0

你非常接近正确。

Tcler的维基有几个例子,其中一些很容易混淆坦率,但是这一个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工作,然后花了字符串。但是,很多年前是固定的,升级到当前版本的修补程序。)

+0

好吧,我升级到Tcl 8.6并尝试了以下gcc命令,但都失败了。 'GCC-LC:\ Tcl的\ lib中-o test.exe的test.c' 'GCC -ltcl -LC:\ Tcl的\ lib中-o test.exe的test.c' 'GCC -ltcl8.6 -LC:\ Tcl \ lib -o test.exe test.c' 'gcc -ltcl8.6 -o test.exe test.c' 'gcc -ltcl -o test.exe test.c' – theClassicFreak

+0

@ socfreak390我不是很确定'-l'选项是什么,但它可能是Windows上的'-lcl86'。它真的取决于文件名是什么,但'tcl86.dll'将意味着使用'-ltcl86'。另外还有Windows上的链接库存在其他问题;近几年来,我在Windows上做了很少的开发工作,我只是不记得确切的细节(除了“匹配文件名”作为解决它们的方法之外)。 –

相关问题