我正在尝试将一段VBA代码移植到Python。这项工作包括调用Windows DLL中的函数。该函数需要一个指向C结构(在VBA中称为“类型”)的指针作为参数。上面提到的结构包含固定长度的字符串以及固定长度的字符串数组。我正在努力寻找一种使用ctypes在Python中表达这一点的方法。在
原始VBA代码包含如下语句:
Public Type elements
elementA As String * 48
elementB(3) As String * 12
End Type
我认为在C语言中可以用以下方式表示:
^{pr2}$到目前为止,我在Python中所做的尝试:
import ctypes
class elements(ctypes.Structure):
_fields_ = [
("elementA", ctypes.create_string_buffer(48)),
("elementB", ctypes.create_string_buffer(12) * 4)
]
我可以成功地声明elementA,但是声明elementB失败了
"TypeError: unsupported operand type(s) for *: 'c_char_Array_12' and 'int'"
怎样才能做到这一点?在
更新1
我可以成功地宣布:
import ctypes
class elements(ctypes.Structure):
_fields_ = [
("elementA", ctypes.c_char * 48),
("elementB", ctypes.c_char * 12 * 4)
]
elementA公开了一个“value”属性,而我找不到使用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'
参见第7.2条和第2.2条)
create_string_buffer
是创建c_char
数组实例的方便函数。但是,字段定义需要C类型,而不是实例。例如:假设您有一个定义如下的C函数:
^{pr2}$要调用此函数,请使用
byref
传递elements
的实例:访问一维
c_char
数组字段,例如elementA
,是返回Python字符串的特殊情况。但是访问一个二维数组,比如elementB
,会返回一个ctypesArray
实例。在elementB
的情况下,有4行,每行包含12列。在sizeof
返回数组的大小(以字节为单位)。例如,elementB
的缓冲区由48个c_char
元素组成,每个元素1个字节:elementB
的c_char
数组作为字符数组,大小写特殊,具有value
和raw
属性。获取value
属性将创建一个Python字符串,该字符串将数组视为以null结尾的C字符串。raw
属性返回整个长度。您还可以使用这些属性指定Python字符串,并且两者都接受一个包含null的字符串。在或者对数组进行切片以获得子字符串:
c_wchar
数组只有value
属性,该属性返回一个unicode
字符串。您可以使用unicode
字符串或(在python2中)8位字符串来设置value
。使用当前ctypes编码对8位字符串进行解码,在Windows上默认为'mbcs'
,否则为'ascii'
。set_conversion_mode
(Python 2)设置默认编码:赋值
'\xc4\x80'
在转换编码设置为UTF-8后起作用:数组是可编辑的:
ctypes数据类型支持Python的缓冲区协议,以便与其他类型进行交互操作:
相关问题 更多 >
编程相关推荐