【发布时间】: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 编写胶水。