【问题标题】:package require with static lib包需要静态库
【发布时间】:2016-09-23 19:22:07
【问题描述】:

我正在开发使用以 C++ 实现的 tcl 包并链接为静态库的应用程序(应用程序是很久以前开发的)。它执行以下操作:

// 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");从 main 开始,包变得不可见。我还注意到没有调用 testlib_Init 和 testlib_SafeInit。我期望它们必须从包需要 testlib 中调用。正如我从文档中了解的那样,每个包都必须在 auto_path 或 tcl_pkgPath 中有 pkg​​Index.tcl ,其中必须包含行 (package ifneeded testlib 1.6 {load {} testlib}),但这里两个变量都不包含这样的索引文件。

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

【问题讨论】:

    标签: tcl


    【解决方案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;
    }
    

    load 调用中的testlib 需要与Tcl_StaticPackage 调用中的testlib 匹配。 package requirepackage ifneededTcl_PkgProvide 中的 testlib 也需要全部匹配(就像出现的 1.6,版本号一样)。


    其他小问题

    另外,您不需要使用 _ANSI_ARGS_ 包装宏。对于我们不再支持的非常古老和蹩脚的编译器来说,这已经完全过时了。只需将_ANSI_ARGS_((Tcl_Interp *interp)) 替换为(Tcl_Interp *interp)。请记住首先调用Tcl_FindExecutable 来初始化Tcl 库的静态部分。如果您没有 argv[0] 可以传递给它,请改用 NULL;它会影响某些平台上的几个更晦涩的内省系统,但您可能并不关心它们。但是,整体初始化库非常很有用:例如,它可以让您确保正确理解文件系统的文件名编码方案!这对编码来说可能有点重要……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-14
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多