2016-09-23 64 views
0

我正在使用在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(口译, “TESTLIB”, “1.6”);从主体,包装变得不可见。另外我注意到testlib_Init和testlib_SafeInit没有被调用。我期待他们必须从package require testlib中调用。根据我的理解,每个软件包必须在auto_path或tcl_pkgPath中包含pkgIndex.tcl,它必须包含行 (package ifneeded testlib 1.6 {load {} testlib}),但这里两个变量都不包含这样的索引文件。

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

回答

1

那么,静态提供软件包最简单的方法就是直接安装它。程序包的init代码应该是调用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需要在testlibTcl_StaticPackage呼叫匹配。 package require,package ifneededTcl_PkgProvide中的testlib也需要全部匹配(如出现1.6,版本号)。


其他的一些小问题

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