将 Ffidl 与 TCL 结合使用返回引用传递字符串和数组
我一直在使用 Ffidl 来处理一些使用 FTDI 驱动程序的设备,并且在大多数情况下它都运行得相当好。我相当确定我失败的地方是因为我对 TCL 如何在幕后处理指针缺乏了解。无论如何,我已经通过执行以下操作获得了有关通过引用传递工作的函数的示例:
::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 *< /code>),因为每当我尝试上述方法时,它们似乎总是返回一些垃圾数据,以及与数组有关的任何数据,因为我什至不知道从哪里开始让它们工作。我很确定这两者背后的过程是相似的,因为一个是字符数组,另一个只是......好吧,其他东西的数组。
任何帮助解决这个问题的帮助将不胜感激。我已经研究了好几天了,当我搜索任何涉及 ffidl 的真正好的例子时,我的 Google-fu 失败了。
编辑:自从我发帖以来,我已经设法使用 ::ffidl::pointer-into-string
命令让字符串正常工作,但遇到了一些困难。它基本上只是查看内存并复制字节,直到它达到零点(我猜)。这不是我认为最佳方法应该是的,因为这似乎不适用于引用,因为我无法通过引用传递指针到内存中的特定位置,并且只是期望它能够正常工作而不会产生任何后果。 (如果我不清楚的话,基本上我要做的就是在当前的内存块中选择一个随机子地址,然后说“嗯,是的。这似乎是放置一些数据的好地方。”这确实是一个坏主意。)
我将继续努力尝试找出如何让数组工作。从复制内存开始,并尝试使用一些二进制扫描
来对字节进行魔法处理。
I've been using Ffidl to work with some devices that use the FTDI drivers, and for the most part it's all working fairly well. I'm fairly certain that the area that I'm failing in comes from my lack of understanding of how TCL handles pointers behind the scenes. In any case, I've gotten examples regarding functions that pass by reference to work by doing something like this:
::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
However, two things that I have not yet managed to figure out are return "by reference" strings (char *
), because they always seem to return some junk data, whenever I try the above approach, as well as anything to do with arrays, because I don't even know where to begin to get those to work. I'm pretty sure that the process behind the two would be similar, since one is an array of characters, and the other would just be an array of... well, something else.
Any help figuring this out would be much appreciated. I've been working on it for days, and my Google-fu is failing when searching for any really good examples involving ffidl.
Edit: since the time of my post, I've managed, with some difficulty to get strings to work, using the ::ffidl::pointer-into-string
command. Which basically just looks at the memory and copies bytes until it reaches a null point (I'm guessing). This is not what I feel the optimum method should be, because this doesn't seem to work for by reference, since I can't pass the pointer by reference to a specific location in memory and just expect it to work without consequence. (If I'm not being clear, basically what I'd be doing is the equivalent of picking a random subaddress in my current block of memory and saying "Hmm, yep. That seems like a good spot to just put some data." which is indeed a bad idea.)
I'm going to keep chugging along to attempt to figure out how to get arrays to work. Starting with copying memory over and trying to work magic the bytes with some binary scan
s.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Tcl确实希望能够管理其值本身的生命周期,并且它使用不可变的值模型。 (现实更复杂,但是请对模型进行编程!)即使值不会改变,您仍然需要复制,除非您可以告诉数据生成器使用 Tcl 自己的内存分配器,
Tcl_Alloc
,尽管在您愿意复制的情况下有许多可用的快捷方式(例如,请参阅Tcl_SetResult
)。这意味着通过引用传入的对象实际上应该映射到一个抽象对象(其表示形式是任意名称,例如
handle-12345
),并且该对象具有许多返回信息的操作关于句柄所代表的对象;对于您的情况,这样的操作之一是返回子字符串的副本,另一个操作可能是返回总长度。唯一的强制操作是处理句柄的显式处置。我知道这听起来很笨拙。这只是实际阻抗不匹配的自然结果。
Tcl really likes to be able to manage the lifetime of its values itself, and it uses an immutable value model. (The reality is more complex, but program to the model, please!) Even if the value wasn't going to change, you'd still need to copy unless you could tell the generator of the data to use Tcl's own memory allocator,
Tcl_Alloc
, though there are a number of shortcuts available in the case where you are happy to copy (seeTcl_SetResult
for example).This means that the object passed in by reference really should be mapped to an abstract object (whose representation is an arbitrary name, such as
handle-12345
) and which has a number of operations on it which return information about the object represented by the handle; one such operation for your case would be to return a copy of a substring, another might be to return the overall length. The only mandatory operation is handling an explicit disposal of the handle.I know this sounds all very clunky. It's just a natural consequence of a real impedance mismatch.
经过一番努力,我终于得出了下面这个【比较虎头蛇尾】的结论。我认为如果我记录我的解决方案,其他寻找这个答案的人(如果有的话)将不胜感激。无论如何,从一开始,使用一些 C 代码,考虑函数
本质上,这一切所做的就是创建一个新的
{1,2,3,4,5}
数组并将其用作 out 指针。接下来,我们将编写 Tcl 包装器:之后,您需要“烹饪”一些接口来使用 make_int_array 函数。你可以这样做:
可能有更好的方法来做到这一点,但这绝对有效,我对此感到高兴。然而,如果有人有更好的方法,我仍然愿意接受想法。
After a lot of work, I finally came to the following [relatively anti-climactic] conclusion. I figured that it would be appreciated for other people looking for this answer (if there ever is anyone) if I were to document my solution. Anyways, from the beginning, with some C code, consider the function
Essentially all this does is create a new array of
{1,2,3,4,5}
and use that for the out pointer. Next, we'll write the Tcl wrapper:After that, you'll need to "cook" a few interfaces to use the make_int_array function. You can do that like so:
There may be a much nicer way to do this, but this definitely worked and I'm happy for that. However, if anyone has a nicer way, I'm still open to ideas.