建议以静态或动态方式在tcl中加载.so包

时间:2010-09-17 06:37:56

标签: package tcl

我有一个托管tcl解释器的可执行文件,以及一个托管扩展的库。 我希望能够动态构建库(加载Tcl的load) 或静态(单个可执行文件,或隐式加载)。

可执行代码:

#ifdef GO_STATIC
    extern int My_ext_Init(Tcl_Interp* interp);
    Tcl_StaticPackage(interp, "my_ext", My_ext_Init, My_ext_Init);
    My_ext_Init(interp);  // THIS SHOULD NOT BE NEEDED !!
    Tcl_SetVariable(interp, "is_statically_linked", "1", TCL_GLOBAL_ONLY);
#else
    Tcl_SetVariable(interp, "is_statically_linked", "0", TCL_GLOBAL_ONLY);
#endif

库Code ..可以是静态库或动态库(.a或.so / .lib或.dll):

int My_ext_Init(Tcl_Interp *interp)
{
 if (Tcl_PkgProvide(interp, "My_ext", "1.0") == TCL_ERROR) {
  return TCL_ERROR;
 }
 Tcl_CreateObjCommand(interp, /*...etc...*/);

}

启动tcl代码:

global is_statically_linked
if {$is_statically_linked} {
    load {} my_ext
} else {
    load my_ext my_ext
}

问题是..我真的不应该像这样呼叫My_ext_Init(interp); 当我评估load {} my_ext

时,应该由Tcl调用

制作社区维基,以便推荐的方式可以放在这里。

1 个答案:

答案 0 :(得分:0)

注册“静态包”是在应用程序初始化例程中完成的,应该在创建主解释器之后完成(但显然在开始运行脚本之前)。当你使用Tcl_Main()来完成翻译工作时,这是一种真正旨在实现程序构建“大愿望”方法的机制。当你这样做时,你的代码回调(通常称为Tcl_AppInit,虽然名称实际上是任意的),你可以指定,哪个是调用Tcl_StaticPackage的理想位置。将在正确的位置调用回调,以便您进行静态包注册。

然而,这些日子都被认为是相当古老的帽子。一个更好的方法是始终使用动态库,而是将所有内容组合在一起作为starkit or starpack。这样做的好处是,您只需要将.so文件构建为启用了存根(强烈建议的)包,然后在打包过程中将它们包含在VFS中。之后,您可以package require完成所有工作。 (或者,您可以在运行时直接在虚拟装载中找到共享库,并直接load它们。)更好的是,您可以提供支持多个平台的单个.kit文件;但是,starpacked可执行文件不能那么灵活,因为对二进制可执行文件的可移植性有一些自然的限制。 : - )