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



我使用ctypes位字段来解析压缩的二进制数据。我将一条记录的数据作为字符串填充到并集中,然后将关键字段作为整数取出。

当缓冲区中没有null,但任何嵌入的null都会导致cytype截断字符串时,这种方法非常有效。

示例:

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='ax00cabc'
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()将正确处理null,而CharArray_set _value()则不会。

但我不知道如何调用原始版本。。。它看起来像一处房产,所以我希望有这样的东西:

ui.buf.raw = 'abcabc'

但这会产生:

AttributeError: 'str' object has no attribute raw

感谢任何指导。(包括完全不同的方法!)

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

您也可以在结构/联合之外创建原始字符串数组:

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

这样,您就不会有任何转换开销。我想知道为什么(c_char*6)在单独使用时与在结构/联合中使用时表现不同。。。

不幸的是,

c_char*6被处理为一个以nul结尾的字符串。改为切换到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)

最新更新