Tcl8.6.5使用_TCL_STUBS tclDecls.h undef TCL_StaticPackage,

Tcl8.6.5使用_TCL_STUBS tclDecls.h undef TCL_StaticPackage,,tcl,stubs,Tcl,Stubs,我正在尝试重建一些最初针对Tcl/Tk8.2构建的软件,它使用libtclstubs.a和libtkstubs.a静态库。 现在我可以从UbuntuXenial,tcl8.6-dev:amd64 8.6.5+dfsg-2软件包中重新编译-ltclstub8.6-ltkstub8.6,但是我得到了链接器错误: undefined reference to `Tcl_StaticPackage' undefined reference to `Tcl_FindExecutable' 我在tclDe

我正在尝试重建一些最初针对Tcl/Tk8.2构建的软件,它使用libtclstubs.a和libtkstubs.a静态库。 现在我可以从UbuntuXenial,tcl8.6-dev:amd64 8.6.5+dfsg-2软件包中重新编译-ltclstub8.6-ltkstub8.6,但是我得到了链接器错误:

undefined reference to `Tcl_StaticPackage'
undefined reference to `Tcl_FindExecutable'
我在tclDecls.h中找到了以下代码块

/* !END!: Do not edit above this line. */

#if defined(USE_TCL_STUBS)
#   undef Tcl_CreateInterp
#   undef Tcl_FindExecutable
#   undef Tcl_GetStringResult
#   undef Tcl_Init
#   undef Tcl_SetPanicProc
#   undef Tcl_SetVar
#   undef Tcl_ObjSetVar2
#   undef Tcl_StaticPackage
#   undef TclFSGetNativePath
#   define Tcl_CreateInterp((tclStubsPtr->tcl_CreateInterp())
#   define Tcl_GetStringResult(interp
               (tclStubsPtr->tcl_GetStringResult(interp))
#   define Tcl_Init(interp) (tclStubsPtr->tcl_Init(interp))
#   define Tcl_SetPanicProc(proc)          (tclStubsPtr->tcl_SetPanicProc(proc))
#   define Tcl_SetVar(interp, varName, newValue, flags) \
        (tclStubsPtr->tcl_SetVar(interp, varName, newValue, flags))
#   define Tcl_ObjSetVar2(interp, part1, part2, newValue, flags) \
        (tclStubsPtr->tcl_ObjSetVar2(interp, part1, part2, newValue, flags))
#endif
显然,前面在头文件中重新定义Tcl_StaticPackage和Tcl_FindExecutable的宏被取消,而不是在这里重新声明。大概我可以在include语句之后在自己的代码中重新定义它们。所以我想我在想,undef语句背后有什么原因吗,它们将来会消失吗?我是不是选择了一个糟糕的版本来构建

作为记录,这是关于一种古老的混合语言Fortran77主程序,它通过C接口启动几个tcl解释器和自定义绘图小部件

编辑:显示链接命令

    gfortran -O3  -fno-automatic -std=legacy -ffixed-form  -rdynamic \
  -o ../bin/xtal_37.exe             aa.lnx_o ab.lnx_o ad.lnx_o ap.lnx_o \
ar.lnx_o at.lnx_o ax.lnx_o ay.lnx_o az.lnx_o bn.lnx_o bt.lnx_o bu.lnx_o \
by.lnx_o cb.lnx_o cf.lnx_o cg.lnx_o ci.lnx_o cl.lnx_o cn.lnx_o cp.lnx_o \
cr.lnx_o cu.lnx_o dd.lnx_o fb.lnx_o fc.lnx_o fe.lnx_o fr.lnx_o fs.lnx_o \
ge.lnx_o gs.lnx_o gt.lnx_o lc.lnx_o lf.lnx_o ls.lnx_o mh.lnx_o ml.lnx_o \
mp.lnx_o nc.lnx_o nm.lnx_o or.lnx_o pa.lnx_o pb.lnx_o pe.lnx_o pg.lnx_o \
pn.lnx_o po.lnx_o pp.lnx_o px.lnx_o pv.lnx_o rb.lnx_o re.lnx_o rf.lnx_o \
rs.lnx_o rv.lnx_o rw.lnx_o sh.lnx_o si.lnx_o sl.lnx_o sp.lnx_o sr.lnx_o \
sx.lnx_o vu.lnx_o xt.lnx_o mx.lnx_o ed.lnx_o cm.lnx_o os.lnx_o dm.lnx_o \
sf.lnx_o     surfin.lnx_o togl.lnx_o tklib.lnx_o datim.lnx_o bitws.lnx_o \
lnblnk.lnx_o qsort.lnx_o          ciftbx.lnx_o hashfunc.lnx_o clearfp.lnx_o \
         -L/usr/X11R6/lib  -L/usr/lib/x86_64-linux-gnu/   -L/usr/lib  \
    -ltclstub8.6 -ltkstub8.6 -ldl -lX11 -lGL -lXmu 
编辑:通过在包含后重新声明defs来显示修复

#include <tk.h>
#
#if defined(USE_TCL_STUBS)
#define Tcl_FindExecutable \
        (tclStubsPtr->tcl_FindExecutable) /* 144 */
#define Tcl_StaticPackage \
        (tclStubsPtr->tcl_StaticPackage) /* 244 */
#endif
-这是可行的,但我不知道为什么它们在第二位是未定义的。

Background 您没有回复我的评论,但出于某些背景:在8.6之前,可以通过Tcl存根表调用Tcl_FindExecutable,这是一个不必要的循环问题:Tcl_FindExecutable必须在创建Tcl_CreateInterp解释器之前调用,不过,初始化存根表需要一个工作的解释器。参见,例如,参考

所以。。。undef Tcl_FindExecutable在刚刚添加宏之后删除该宏,以减少意外使用的可能性,但不会阻止它,如修补程序所示

建议
您的应用程序xtal.exe似乎根本不打算作为一个Tcl扩展来获得存根机制的好处,所以在编译步骤中将它构建为一个独立的应用程序,使用-ltcl86并省略-DUSE_Tcl_存根?在任何情况下,为了获得对Tcl_FindExecutable的有效引用,您必须包括-ltcl86,无论是否使用存根。

您可以发布您的确切链接器调用吗?毫无疑问,作为一个盲人,不用DUSE_TCL_存根编译吗?谢谢卡尔文先生。显然,在xtal中,在创建解释器之后,调用Tcl_FindExecutable时没有参数,只是为了初始化Tcl搜索路径。随后,使用空解释器调用Tcl_StaticPackage以注册内置扩展。它是使用存根构建的,因此单个二进制文件可以针对任何已安装的tcl>8.2运行,这在我从386切换到64位linux之前都很好。也许我相信一个Tcl核心?可能有多个解释器实例,因此仅初始化搜索路径并将编译的扩展名编译成其中一个实例是没有意义的。不确定。那是很久以前的事了。