我正在尝试使用 Python 的 ctypes 库来访问扫描库SANE中的一些方法。这是我第一次使用 ctypes,也是我一年多以来第一次不得不处理 C 数据类型,所以这里有一个公平的学习曲线,但我认为即使没有这个特定的声明也会很麻烦:
extern SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only);
首先,我已经成功处理了SANE_Status
(an enum) 和SANE_Bool
(a typedef to c_int
)。这些都很简单。另一方面,第一个参数给我带来了各种各样的悲伤。我不熟悉“ ***
”符号,到目前为止,我的示踪子弹只产生了垃圾数据。如何格式化此函数的输入,以便我可以读回我的 Python 结构对象列表?作为参考,被引用的 C 结构是:
typedef struct
{
SANE_String_Const name; /* unique device name */
SANE_String_Const vendor; /* device vendor string */
SANE_String_Const model; /* device model name */
SANE_String_Const type; /* device type (e.g., "flatbed scanner") */
}
SANE_Device;
其中SANE_String_Const
定义为c_char_p
.
我的这个对象的 Python/ctypes 版本是:
class SANE_Device(Structure):
_fields_ = [
("name", c_char_p),
("vendor", c_char_p),
("model", c_char_p),
("type", c_char_p)]
关于我应该传递什么的建议,以便我可以从中获得预期的行为(结构对象列表)?所有回应表示赞赏。
更新1:
使用以下内容,我能够检索到正确的 SANE_Device Python 结构:
devices = pointer(pointer(pointer(SANE_Device())))
status = libsane.sane_get_devices(devices, c_int(0))
print status, devices, devices.contents.contents.contents.name
但是,1) 糟糕和 2) 似乎只有在只有一个结果时才会起作用。我不能 len() on devices.contents.contents
or devices.contents.contents.contents
。我如何确定结果的数量?SANE 文档指定“如果函数成功执行,它会存储一个指向 *device_list 中指向 SANE_Device 结构的指针的 NULL 终止数组的指针”。建议?
更新 2:
我能够传递一个十项数组,然后使用以下方法访问第一个元素:
devices = pointer(pointer(pointer((SANE_Device * 10)())))
status = libsane.sane_get_devices(devices, c_int(0))
print status, devices, devices.contents.contents.contents[0].name
但是,十显然是一个任意数字,我无法确定实际结果的数量。devices.contents.contents.contents[1].name
在仅连接一个设备时尝试访问会导致分段错误。必须有一种适当的方法来处理像 ctypes 中这样的可变长度构造。