2016-09-23 67 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;它會在一些平臺上影響一些比較模糊的內省系統,但是你可能不關心它們。但是,初始化庫總體上是很有用例如,它可以讓你確保正確理解文件系統的文件名編碼方案!這可能對代碼有點重要...