package需要使用静态lib

时间:2016-09-23 07:34:31

标签: tcl

我正在开发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}),但这里两个变量都不包含这样的索引文件。

这是提供包裹的正确方法吗?是否有与使用静态库提供包相关的文档?

1 个答案:

答案 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相匹配。 testlibpackage requirepackage ifneeded中的Tcl_PkgProvide也需要全部匹配(版本号1.6的出现次数。)

其他小问题

此外,您不需要使用_ANSI_ARGS_包装器宏。对于我们不再支持的真正古老而糟糕的编译器而言,这已经完全过时了。只需将_ANSI_ARGS_((Tcl_Interp *interp))替换为(Tcl_Interp *interp)即可。并记得首先调用Tcl_FindExecutable来初始化Tcl库的静态部分。如果您没有argv[0]可以传入,请改用NULL;它会在某些平台上影响一些比较模糊的内省系统,但你可能并不关心它们。但是,初始化库总体上非常非常有用:例如,它可以确保正确理解文件系统的文件名编码方案!这对代码来说可能有点重要......