2011-04-08 35 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 
} 

可能有更好的方法来做到这一点,但这绝对有效,我很高兴。但是,如果任何人有更好的方式,我仍然对想法持开放态度。

相关问题