我有一个托管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
制作社区维基,以便推荐的方式可以放在这里。
答案 0 :(得分:0)
注册“静态包”是在应用程序初始化例程中完成的,应该在创建主解释器之后完成(但显然在开始运行脚本之前)。当你使用Tcl_Main()
来完成翻译工作时,这是一种真正旨在实现程序构建“大愿望”方法的机制。当你这样做时,你的代码回调(通常称为Tcl_AppInit
,虽然名称实际上是任意的),你可以指定,哪个是调用Tcl_StaticPackage
的理想位置。将在正确的位置调用回调,以便您进行静态包注册。
然而,这些日子都被认为是相当古老的帽子。一个更好的方法是始终使用动态库,而是将所有内容组合在一起作为starkit or starpack。这样做的好处是,您只需要将.so
文件构建为启用了存根(强烈建议的)包,然后在打包过程中将它们包含在VFS中。之后,您可以package require
完成所有工作。 (或者,您可以在运行时直接在虚拟装载中找到共享库,并直接load
它们。)更好的是,您可以提供支持多个平台的单个.kit
文件;但是,starpacked可执行文件不能那么灵活,因为对二进制可执行文件的可移植性有一些自然的限制。 : - )