2013-12-13 76 views
1

我對tcl非常陌生。如何在tcl中的加載命令上使用interp arg?

我想加載一個DLL使用加載命令,但我得到一個未定義的符號錯誤。

我很確定這個消息暗示dll是針對特定的(專有)解釋器的。

如果我嘗試從「希望」執行加載,則會出現錯誤,但如果我從專有解釋器執行加載,則加載正常。

我看到在load命令中,我可以傳入packageName和interp。 我在想,如果我通過專有解釋器,我可能能夠得到這個工作,但如果我傳遞給解釋器的路徑,我會收到一條錯誤消息,說它不能解釋解釋器。 有人知道interp =期待什麼嗎?

順便說一句,我不能只使用專有的解釋器,因爲我真的只是試圖從ruby調用tcl命令,而我沒有頭文件來編譯ruby與該解釋器。

該命令,我收到一條錯誤消息,說有和未定義的符號。

回答

2

load命令做兩兩件事:

  1. 它位於指定的共享庫並在此過程使得它「存在」。 (用於此的OS API變化;而在Unix上通常是dlopen(),並且在Windows上是LoadLibraryEx()

  2. 然後,它所處的初始化函數庫中,並調用它,傳遞一個句柄是解釋從圖書館獲得功能。初始化函數具有通常從庫的名稱派生的名稱;如果您正在加載foobar72.dll,則該函數將被稱爲Foobar_Init。 TCL始終假定初始化函數的類型簽名是這樣的:

    int InitFunc(Tcl_Interp *interp); 
    

我猜,第一階段工作,但第二階段失敗;不存在初始化函數,而且該庫不適用於Tcl。 (特別是,它也不會不知道如何使用Tcl的API來註冊命令,設置變量等)

的方式來解決這個問題是:

  1. 使用工具,如SWIG創建一個包裝庫。
  2. 使用像ffidl這樣的Tcl擴展來執行直接的API調用。
  3. 使用Tcl擴展如critcl在Tcl中編寫包裝庫。
  4. 用手寫包裝。 (這是不是很辛苦IMO,但情況因人而異。)

你應該知道是c的API由痛飲浮出水面和ffidl感到非常奇怪在Tcl中正常;你通常需要在它們周圍編寫更多的Tcl代碼,以使界面更自然。(這不是對這些API的批評;只是承認C語言和Tcl語言對於「自然」的含義有不同的概念。)

要說你最好的方法是什麼,我們需要相當更多的信息。你可能更好地表達這個問題。

+0

如果你想要一個相當典型的初始化函數來看,[TDBC包的一個](http://core.tcl.tk/tdbc/artifact/5e875b2fe4177fa040f2c6330b7d3d0ae5e33c71?ln=194-223)是非常合理的。它調用'Tcl_InitStubs'(獲得API/ABI訪問),用'Tcl_CreateObjCommand'註冊一些命令,然後調用'Tcl_PkgProvideEx'來標記包是否存在。 –

+0

謝謝,我也在嘗試swig方法,但我遇到了問題以及看到:http://stackoverflow.com/questions/20587374/make-fails-on-swig-create-ruby-wrapper – nPn

+0

@nPn :我自己並不使用SWIG方法,但是當連接C++(而不是C)時,您最好手工編寫包裝器。當然,它的難度取決於細節,但要記住的關鍵是Tcl是作爲C庫實現的,所有回調函數都必須是函數(_not_方法或不直接),並且具有C鏈接。 –