【问题标题】:Attempting to pass pointers to API function from Tcl试图从 Tcl 传递指向 API 函数的指针
【发布时间】:2014-04-02 19:01:19
【问题描述】:

我正在尝试编写一个 Tcl 脚本来连接一个 FTDI USB 设备(Windows 平台)。我已经从 FTDI API 获得了具有单个输入参数的函数,但是一个名为“FT_GetDeviceInfoDetail”的 API 函数让我很伤心。

API函数调用如下:

FT_STATUS FT_GetDeviceInfoDetail (DWORD dwIndex, LPDWORD lpdwFlags, LPDWORD lpdwType, LPDWORD lpdwID, LPDWORD lpdwLocId, PCHAR pcSerialNumber, PCHAR pcDescription, FT_HANDLE *ftHandle)

其中 LPDWORD、PCHAR 和 FT_HANDLE 都是指向不同大小的内存空间的指针。

使用 ffidl,我这样指定函数调用:

ffidl::callout _GetDeviceInfoDetail {uint32 pointer-var pointer-var \
            pointer-var pointer-var pointer-var pointer-var \
            pointer-var} uint32 \
        [ffidl::symbol $dll FT_GetDeviceInfoDetail]

这就是有趣的地方。在 Tcl 中,对于传递给 API 的所有指针参数,我设置如下变量: 设置变量名 [二进制格式s 0]

当我调用函数时,我为所有指针传递了变量名(即“foo”,而不是“$foo”),并且(有点神奇地)函数返回“OK”状态。此时,理论上,我传入的变量的内容会包含一些二进制字符串格式的数据。

然后我尝试通过执行以下操作“重新构造”二进制数据的字符串表示:

[binary scan $foo s outstring]

此时 Windows 介入并告诉我“Tclsh 已停止工作”。

我怀疑该函数正在为一个或多个变量覆盖内存空间,但我不确定该怎么做。到目前为止,我想到的最好的想法可能是为 Tcl 编写一个 C 扩展来调用 API,填充数据结构,然后以某种方式将结构传递回 Tcl。

谁能指出我在纯 Tcl 中执行此操作的方法? (对不起双关语;我无法抗拒!)

【问题讨论】:

  • 回调对于 ffidl IIRC 来说很棘手。使用不同的方法可能会更好,例如构建一个小的扩展包,以便可以用 C 编写胶水。

标签: c pointers tcl


【解决方案1】:

我的 ffidl 有点生锈,所以请耐心等待。我的怀疑是因为您要移交的变量名称设置为:

set varname [binary format s 0]

lpSerialNumber 和 lpDescription 字段导致覆盖。这两个字段都可以大到 16 个字节。对于这些字段,初始化为 16 字节空字符串的变量可能会起作用,即

set serno [string repeat "\0" 16]

应该为您提供 lpSerialNumber 字段所需的空间,例如。无论如何,在这种情况下我会尝试。

【讨论】:

  • 感谢您的建议。我试了一下,然后函数调用给了我消息“参数1必须是二进制字符串”...
【解决方案2】:

在尝试了各种二进制格式选项后,我发现如果我执行“set foo [binary format xn]”(其中“foo”是我希望创建的指针,“n”是要创建的字节数分配空间),然后将名称 foo 作为函数调用中的指针传递,该函数似乎可以正常工作(至少 Tcl 解释器不会崩溃!)。

【讨论】:

    猜你喜欢
    • 2015-08-05
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2010-10-31
    • 2021-07-17
    相关资源
    最近更新 更多