我正在开发app,它使用在C ++中实现的tcl包并作为静态库链接(app很久以前开发)。它确实如下:
// Library code
extern "C" int testlib_SafeInit _ANSI_ARGS_((Tcl_Interp *interp))
{
return Tcl_PkgProvide(interp, "testlib", "1.6");
}
extern "C" int testlib_Init _ANSI_ARGS_((Tcl_Interp *interp))
{
return testlib_SafeInit(interp);
}
// Application code
extern "C" int testlib_SafeInit _ANSI_ARGS_((Tcl_Interp *interp));
extern "C" int testlib_Init _ANSI_ARGS_((Tcl_Interp *interp));
int main()
{
Tcl_Interp* interp = Tcl_CreateInterp();
Tcl_Init(interp);
Tcl_PkgProvide(interp, "testlib", "1.6");
Tcl_StaticPackage(interp, "testlib", testlib_Init, testlib_SafeInit);
Tcl_Eval(interp, "package require testlib");
std::cout << "Res = " << Tcl_GetStringResult(interp);
return 0;
}
当我删除行Tcl_PkgProvide(interp,“testlib”,“1.6”)时;从主,包变得无形。另外我注意到没有调用testlib_Init和testlib_SafeInit。我希望它们必须从package require testlib中调用。据我所知,每个包必须在auto_path或tcl_pkgPath中包含pkgIndex.tcl,其中必须包含line (package ifneeded testlib 1.6 {load {} testlib}),但这里两个变量都不包含这样的索引文件。
这是提供包裹的正确方法吗?是否有与使用静态库提供包相关的文档?
答案 0 :(得分:1)
嗯,静态提供软件包的最简单方法就是直接安装它。包初始化代码应该是调用Tcl_PkgProvide
的代码 - 你通常不会从main()执行此操作 - 除非你想安装代码,否则你可能根本不需要Tcl_StaticPackage
进入副译员。
int main(int argc, char*argv[])
{
Tcl_FindExecutable(argv[0]);
Tcl_Interp* interp = Tcl_CreateInterp();
Tcl_Init(interp);
testlib_Init(interp);
// OK, setup is now done
Tcl_Eval(interp, "package require testlib");
std::cout << "Res = " << Tcl_GetStringResult(interp) << "\n";
return 0;
}
但是,我们可以转向使用Tcl_StaticPackage
。这允许代码说“不是用这种名称加载DLL,我已经知道代码:这里是它的入口点”。如果您这样做,则需要还要安装package ifneeded
脚本;这些只通过脚本API完成。
int main(int argc, char*argv[])
{
Tcl_FindExecutable(argv[0]);
Tcl_Interp* interp = Tcl_CreateInterp();
Tcl_Init(interp);
Tcl_StaticPackage(interp, "testlib", testlib_Init, testlib_SafeInit);
Tcl_Eval(interp, "package ifneeded testlib 1.6 {load {} testlib}");
// OK, setup is now done
Tcl_Eval(interp, "package require testlib");
std::cout << "Res = " << Tcl_GetStringResult(interp) << "\n";
return 0;
}
testlib
来电中的load
需要与testlib
来电中的Tcl_StaticPackage
相匹配。 testlib
,package require
和package ifneeded
中的Tcl_PkgProvide
也需要全部匹配(版本号1.6
的出现次数。)
此外,您不需要使用_ANSI_ARGS_
包装器宏。对于我们不再支持的真正古老而糟糕的编译器而言,这已经完全过时了。只需将_ANSI_ARGS_((Tcl_Interp *interp))
替换为(Tcl_Interp *interp)
即可。并记得首先调用Tcl_FindExecutable
来初始化Tcl库的静态部分。如果您没有argv[0]
可以传入,请改用NULL
;它会在某些平台上影响一些比较模糊的内省系统,但你可能并不关心它们。但是,初始化库总体上非常非常有用:例如,它可以确保正确理解文件系统的文件名编码方案!这对代码来说可能有点重要......