Python ctypes - 当字符串嵌入null时设置c_char数组?

时间:2014-10-09 12:22:41

标签: python python-2.7 ctypes

我使用ctypes位字段来剖析紧密压缩的二进制数据。我将一个记录的数据作为字符串填充到一个联合中,然后将关键字段作为整数拉出。

当缓冲区中没有空值时,这很有用,但任何嵌入的空值都会导致细胞截断字符串。

示例:

from ctypes import *

class H(BigEndianStructure):
    _fields_ = [ ('f1', c_int, 8),
                 ('f2', c_int, 8),
                 ('f3', c_int, 8),
                 ('f4', c_int, 2)
                 # ...
                 ]

class U(Union):
    _fields_ = [ ('fld', H),
                 ('buf', c_char * 6)
                 ]

# With no nulls, works as expected...
u1 = U()
u1.buf='abcabc'
print '{} {} {} (expect: 97 98 99)'.format(u1.fld.f1, u1.fld.f2, u1.fld.f3)

# Embedded null breaks it...  This prints '97 0 0', NOT '97 0 99'
u2 = U()
u2.buf='a\x00cabc'
print '{} {} {} (expect: 97 0 99)'.format(u2.fld.f1, u2.fld.f2, u2.fld.f3)

浏览ctypes源代码,我看到两个设置char数组的方法,CharArray_set_value()和CharArray_set_raw()。似乎CharArray_set_raw()将正确处理空值,而CharArray_set_value()则不会。

但是我无法弄清楚如何调用原始版本...它看起来像一个属性,所以我希望有类似的东西:

ui.buf.raw = 'abcabc'

但是产生了:

AttributeError: 'str' object has no attribute raw

任何指导意见。 (包括一种完全不同的方法!)

(注意:我需要每秒处理数千条记录,因此效率至关重要。使用数组理解来填充结构中的字节数组,但速度要慢100倍。)

2 个答案:

答案 0 :(得分:0)

不幸的是,

c_char*6被处理为以null结尾的字符串。切换到c_byte*6,但却失去了使用字符串初始化的便利性:

from ctypes import *

class H(BigEndianStructure):
    _fields_ = [ ('f1', c_int, 8),
                 ('f2', c_int, 8),
                 ('f3', c_int, 8),
                 ('f4', c_int, 2)
                 # ...
                 ]

class U(Union):
    _fields_ = [ ('fld', H),
                 ('buf', c_byte * 6)
                 ]

u1 = U()
u1.buf=(c_byte*6)(97,98,99,97,98,99)
print '{} {} {} (expect: 97 98 99)'.format(u1.fld.f1, u1.fld.f2, u1.fld.f3)

u2 = U()
u2.buf=(c_byte*6)(97,0,99,97,98,99)
print '{} {} {} (expect: 97 0 99)'.format(u2.fld.f1, u2.fld.f2, u2.fld.f3)

输出:

97 98 99 (expect: 97 98 99)
97 0 99 (expect: 97 0 99)

答案 1 :(得分:0)

您还可以在struct / union之外创建原始字符串数组:

mystring = (c_char * 6).from_buffer(u2)
print mystring.raw

这样您就不会有任何转化费用。 我想知道为什么(c_char * 6)在单独使用时表现不同而在结构/联盟中使用...