如何静态链接最初打算用作Tcl扩展的库?
我有一个库,最初是作为可加载的Tcl扩展构建的。我现在尝试将它用于一个稍微不同的用途(一个带有libtecla的交互式shell,用于制表符完成和历史记录),但目前无法使如何静态链接最初打算用作Tcl扩展的库?,tcl,Tcl,我有一个库,最初是作为可加载的Tcl扩展构建的。我现在尝试将它用于一个稍微不同的用途(一个带有libtecla的交互式shell,用于制表符完成和历史记录),但目前无法使Tcl_StaticPackage()和load{}$lib组合起作用。奇怪的是,虽然不工作,但它也不会产生错误 我已将演示问题所需的代码缩减为: main.cpp #include <stdio.h> #include <tcl.h> extern "C" { int Demolib_Init
Tcl_StaticPackage()
和load{}$lib
组合起作用。奇怪的是,虽然不工作,但它也不会产生错误
我已将演示问题所需的代码缩减为:
main.cpp
#include <stdio.h>
#include <tcl.h>
extern "C" {
int Demolib_Init(Tcl_Interp *);
int Demolib_SafeInit(Tcl_Interp *);
}
int main(int argc, char *argv[])
{
Tcl_Interp *interp;
interp = Tcl_CreateInterp();
if (!interp)
{
perror("Couldn't create interpreter");
return 1;
}
if (TCL_OK != Tcl_Init(interp))
{
perror("Couldn't initialize Tcl");
return 2;
}
Tcl_StaticPackage(interp, "Demolib", Demolib_Init, Demolib_SafeInit);
printf("Via 'load'...\n");
if (TCL_OK != Tcl_Eval(interp, "load {} Demolib"))
{
fprintf(stderr, "Err : %s\n", Tcl_GetStringResult(interp));
}
else
{
printf("Ok : %s\n", Tcl_GetStringResult(interp));
}
printf("\nVia 'Demolib_Init()'...\n");
Demolib_Init(interp);
return 0;
}
#include <tcl.h>
#include <stdio.h>
#include "demolib.h"
#ifdef __cplusplus
extern "C" {
#endif
int DLLEXPORT Demolib_Init(Tcl_Interp *interp)
{
printf("Pre-stubs\n");
#ifdef USE_TCL_STUBS
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL)
{
return TCL_ERROR;
}
#endif
printf("Pre-provide\n");
if (Tcl_PkgProvide(interp, "Demolib", "0.0") == TCL_ERROR)
{
return TCL_ERROR;
}
printf("Pre-return\n");
return TCL_OK;
}
int DLLEXPORT Demolib_SafeInit(Tcl_Interp *interp)
{
return Demolib_Init(interp);
}
#ifdef __cplusplus
}
#endif
但是,无论是Demolib\u Init()
还是Demolib\u SafeInit()
都不会被调用。我可以直接调用它,可以说它更整洁(没有Tcl_Eval(…)
call),但我想了解(没有)发生了什么。在最后一个应用程序中,加载{}…
的时间将由脚本确定,因此需要此功能
请注意,我故意不调用Tcl_Main()
或进入Tcl事件循环-libtecla最终将提供提示
我错过了什么?在Windows上使用MSVC 2013和Tcl 8.6尝试使用提供的两个文件:
C:\src\Files\DemoTcl>cl -nologo -I/opt/tcl/include -D_DEBUG -Od -Zi -MDd -c main.cpp
main.cpp
C:\src\Files\DemoTcl>cl -nologo -I/opt/tcl/include -D_DEBUG -Od -Zi -MDd -c demolib.cpp
demolib.cpp
C:\src\Files\DemoTcl>link -nologo -subsystem:console main.obj demolib.obj \opt\tcl\lib\tcl86.lib
Creating library main.lib and object main.exp
C:\src\Files\DemoTcl>main.exe
Via 'load'...
Ok :
Via 'Demolib_Init()'...
Pre-stubs
Pre-provide
Pre-return
如果我们将Tcl_StaticPackage调用更改为以下内容:
Tcl_StaticPackage(NULL, "Demolib", Demolib_Init, Demolib_SafeInit);
那么新的可执行输出是:
Via 'load'...
Pre-stubs
Pre-provide
Pre-return
Ok :
Via 'Demolib_Init()'...
Pre-stubs
Pre-provide
Pre-return
我认为应该添加一个Tcl_FindExecutable(argv[0])代码>也很早就开始了,尽管这不会影响出现的问题
Tcl_StaticPackage的文档巧妙地指出,interp参数指向一个解释器,如果该解释器不为NULL,则该解释器中的包已经加载。我认为这与它的构建和链接方式有关,但这是一个我不太了解的领域。真遗憾——我自信地期待着你通常的全面解释。我没有明确说明的是,虽然文件解决方案最好是静态链接到库,但在这种简化的情况下,我只是将两个.o链接到一个可执行文件中。上面的注释应该是“…而最终解决方案…”嗯-似乎应该在“通过‘加载’”之后立即打印出Pre-provide等等。所以not ok then.ok-您需要在Tcl\u StaticPackage调用中使用NULL。请参见编辑。非常好,帕特,谢谢。在这个案例中,我对文档的阅读似乎减少到了略微不充分的“Tcl_Interp*-我有一个这样的文档!”现在这很微妙+1.
Via 'load'...
Pre-stubs
Pre-provide
Pre-return
Ok :
Via 'Demolib_Init()'...
Pre-stubs
Pre-provide
Pre-return