2010-09-17 26 views
0

我有一個託管tcl解釋器的可執行文件和一個託管擴展的庫。 我希望能夠動態地構建庫(加載Tcl的load) 或靜態(單個可執行文件,或隱式加載)。建議在tcl中靜態或動態加載.so軟件包

所述可執行代碼:

#ifdef GO_STATIC 
    extern int My_ext_Init(Tcl_Interp* interp); 
    Tcl_StaticPackage(interp, "my_ext", My_ext_Init, My_ext_Init); 
    My_ext_Init(interp); // THIS SHOULD NOT BE NEEDED !! 
    Tcl_SetVariable(interp, "is_statically_linked", "1", TCL_GLOBAL_ONLY); 
#else 
    Tcl_SetVariable(interp, "is_statically_linked", "0", TCL_GLOBAL_ONLY); 
#endif 

庫代碼..可以是靜態或動態庫(.A或.so /的.lib或.dll):

int My_ext_Init(Tcl_Interp *interp) 
{ 
if (Tcl_PkgProvide(interp, "My_ext", "1.0") == TCL_ERROR) { 
    return TCL_ERROR; 
} 
Tcl_CreateObjCommand(interp, /*...etc...*/); 

} 

啓動TCL代碼:

global is_statically_linked 
if {$is_statically_linked} { 
    load {} my_ext 
} else { 
    load my_ext my_ext 
} 

問題是..我真的不應該叫My_ext_Init(interp);因爲它 當我評估時應由Tcl調用load {} my_ext

製作社區wiki,以便推薦的方式可以放在此處。

+1

您不會說可執行文件中的第一個代碼段放在哪裏。這很重要... – 2010-09-17 08:19:16

回答

0

註冊一個「靜態包」在您的應用程序init例程中完成,並且應該在創建主解釋器之後完成(但顯然在開始運行腳本之前)。當你使用Tcl_Main()來做解釋器的工作時,這是一個真正設計用於編程的「大願望」方法的機制。當你這樣做的時候,你的代碼有一個回調(通常稱爲Tcl_AppInit,雖然這個名字實際上是任意的),你可以指定哪個是呼叫Tcl_StaticPackage的理想地方。回調將在正確的時間點進行靜態包註冊。

但是,這些天都被認爲是相當古老的帽子。更好的方法是始終使用動態庫,並將所有內容打包爲starkit or starpack。這樣做的好處是您只需要將您的.so文件構建爲存根啓用(強烈推薦)的包,然後在打包過程中將它們包含在VFS中。之後,你可以做package require,它會一切正常。 (或者,您可以在運行時找到虛擬安裝中的共享庫,並直接在load上找到它們)。更妙的是,您可以提供支持多種平臺的單個文件:.kit;但是星形封裝的可執行文件不能很靈活,因爲對二進制可執行文件的可移植性有一些自然的限制。 :-)