【发布时间】:2014-07-27 03:03:15
【问题描述】:
我正在尝试将一段 VBA 代码移植到 Python。这项工作包括调用 Windows DLL 中的函数。该函数需要一个指向 C 结构的指针(在 VBA 中,它们被称为“类型”)作为参数。提到的结构包含固定长度的字符串以及固定长度的字符串数组。我正在努力寻找一种使用 ctypes 在 Python 中表达这一点的方法。
原始 VBA 代码包含如下语句:
Public Type elements
elementA As String * 48
elementB(3) As String * 12
End Type
我认为这在 C 中可以用以下方式表示:
struct elements
{
char elementA[48];
char elementB[4][12];
}
到目前为止我在 Python 中的尝试:
import ctypes
class elements(ctypes.Structure):
_fields_ = [
("elementA", ctypes.create_string_buffer(48)),
("elementB", ctypes.create_string_buffer(12) * 4)
]
我可以成功声明 elementA,尽管声明 elementB 失败并显示
"TypeError: *: 'c_char_Array_12' 和 'int' 的操作数类型不受支持"
如何以正确的方式做到这一点?
更新 #1
我可以成功声明以下内容:
import ctypes
class elements(ctypes.Structure):
_fields_ = [
("elementA", ctypes.c_char * 48),
("elementB", ctypes.c_char * 12 * 4)
]
elementA 暴露了一个“值”属性,而我找不到使用 elementB 的方法。如何阅读或更改其内容?
更新 #2
我想我理解这种行为。
>>> e = elements()
>>> e.elementA
''
>>> e.elementA = 'test'
>>> e.elementA
'test'
>>> e.elementB
<__main__.c_char_Array_12_Array_4 object at 0x9878ecc>
>>> e.elementB[0][:] == '\x00' * 12
True
>>> e.elementB[0][:]
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> e.elementB[0][:] = 'test'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Can only assign sequence of same size
>>> e.elementB[0][:] = 'test' + '\x00' * 8
>>> e.elementB[0][:]
'test\x00\x00\x00\x00\x00\x00\x00\x00'
>>> testB = 'abcde'
>>> e.elementB[0][:] = testB + '\x00' * ( ctypes.sizeof(e.elementB[0]) - len(testB) )
>>> e.elementB[0][:]
'abcde\x00\x00\x00\x00\x00\x00\x00'
>>> e.elementB[0][:].rstrip('\x00')
'abcde'
>>> e.elementB[0].value
'abcde'
>>> e.elementB[0].value = 'abcdef'
>>> e.elementB[0][:]
'abcdef\x00\x00\x00\x00\x00\x00'
(这个问题指的是 Python 2.6 和 2.7。)
【问题讨论】:
-
@eryksun 感谢您的帮助。我将您的评论纳入了我的问题,但是,我在使用它时遇到了困难。 2D-char-array 没有公开任何类似“值”属性的东西,我不知道如何读取或写入该数组。
-
@eryksun 再次感谢。我想我现在理解了这种行为 - 请参阅我的问题的最后更新。你想把这个总结成一个答案吗?
标签: python c vba struct ctypes