2011-04-08 61 views
1

我一直在使用Ffidl來處理一些使用FTDI驅動程序的設備,而且大多數情況下它都工作得很好。我相當肯定,我失敗的領域來自我對TCL如何處理幕後指針的理解。在任何情況下,我已經得到了關於通過引用傳遞通過做這樣的工作函數的例子:在TCL中使用Ffidl返回通過引用的字符串和數組

::ffidl::callout rpbrd {pointer-var} int \ 
     [ffidl::symbol [ffidl::find-lib library] returns_pass_by_reference_double] 
set dbl_ptr = [binary format [::ffidl::info format double] 1] 
set my_int = [rpbrd dbl_ptr] 
binary scan $dbl_ptr [::ffidl::info format double] my_dbl 
puts $my_dbl 

但是,我還沒有設法弄清楚兩件事情是迴歸「引用」的字符串(char *),因爲他們似乎總是返回一些垃圾數據,每當我嘗試上述方法時,以及與數組有關的任何事情,因爲我甚至不知道從哪裏開始讓這些工作。我很確定這兩者背後的過程是相似的,因爲一個是一個字符數組,另一個只是一個數組......其他的東西。

任何幫助搞清楚這一點將不勝感激。我一直在爲它工作好幾天,當我搜索任何涉及ffidl的很好的例子時,我的Google-fu失敗了。

編輯:自從我的文章發佈以來,我使用::ffidl::pointer-into-string命令管理了一些難以獲得字符串的工作。基本上只是看內存和複製字節,直到它達到一個零點(我猜)。這不是我認爲最佳方法應該是的,因爲這似乎不適用於引用,因爲我無法通過引用指向內存中的特定位置來傳遞指針,只是期望它在沒有後果的情況下工作。 (如果我不清楚,基本上我會做的就是在當前的內存塊中選擇一個隨機子地址,然後說:「嗯,是的,這似乎是放置一些數據的好地方。」這確實是一個糟糕的主意。)

我將繼續嘗試弄清楚如何讓數組工作。從複製內存開始,並嘗試使用一些binary scan s的魔法字節。

回答

1

Tcl 真的喜歡能夠管理其值本身的生命週期,它使用不可變的價值模型。 (現實情況更復雜,但請編程到模型中!)即使值不會改變,您仍然需要複製,除非您可以告訴數據生成器使用Tcl自己的內存分配器, Tcl_Alloc,但在您喜歡複製的情況下有多個快捷方式可用(例如,請參閱Tcl_SetResult)。

這意味着,通過引用傳入的對象確實應映射到抽象對象(其表示是任意名稱,例如handle-12345),並且其上有許多操作,它們返回有關由手柄;你的情況下的一個這樣的操作將返回一個子串的副本,另一個可能會返回總長度。唯一的強制操作是處理一個明顯的處理。

我知道這聽起來都非常笨重。這只是一個真正的阻抗不匹配的自然結果。

+0

雖然這有助於我理解Tcl如何在「幕後」工作,但我不確定我是如何使用它將Ffidl指向內存位置的指針解釋爲整數數組。 並不是說這不能回答這個問題,必然只是我不知道如何應用它。 – ashays 2011-04-08 15:18:32

+0

我不太清楚我的實現是否真的使用了你特別提到的內容,但我認爲這有助於我在某種程度上形成我的解決方案。爲此,我感謝你。 – ashays 2011-04-08 16:34:48

0

經過大量的工作,我終於得出以下[相對反高潮]的結論。我想,如果我要記錄我的解決方案,那麼對於尋找這個答案的其他人(如果有人有任何問題),我將不勝感激。不管怎麼說,從一開始,有一些C代碼,考慮功能

void make_int_array(int*& out) { 
    int* a = new int[5]; 
    for (int i = 0; i < 5; i++) { 
     a[i] = i+1; 
    } 
    out = a; 
} 

從本質上講這一切都爲創造{1,2,3,4,5}一個新的陣列和使用,對於出指針。接下來,我們將編寫Tcl包裝:

::ffidl::callout _make_int_array {pointer-var} void \ 
        [::ffidl::symbol ffidltest.dll make_int_array] 

之後,你需要「煮」了一些接口使用make_int_array功能。你可以這樣做:

proc make_int_array {} { 
    set ints 5 
    set intsize [::ffidl::info sizeof int] 
    set bytesize [expr $intsize * $ints] 

    set ptr [binary format [::ffidl::info format int] 1] 
    _make_int_arrayptr ptr 
    binary scan $ptr i ptr 

    binary scan [::ffidl::peek $ptr $bytesize] \ 
       [::ffidl::info format int]$ints out 
    return $out 
} 

可能有更好的方法來做到這一點,但這絕對有效,我很高興。但是,如果任何人有更好的方式,我仍然對想法持開放態度。

相關問題