Python ctypes - Setting c_char array when string has embedded null? -
i'm using ctypes bit fields dissect tightly packed binary data. stuff record's worth of info union string, pull out key fields integers.
this works great when there no nulls in buffer, embedded nulls cause cytpes truncate string.
example:
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) ] # no nulls, works 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... 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)
browsing ctypes source, see 2 methods set char array, chararray_set_value() , chararray_set_raw(). appears chararray_set_raw() handle nulls whereas chararray_set_value() not.
but can't figure out how invoke raw version... looks property, i'd expect like:
ui.buf.raw = 'abcabc'
but yields:
attributeerror: 'str' object has no attribute raw
any guidance appreciated. (including different approach!)
(note: need process thousands of records per second, efficiency critical. using array comprehension stuff byte array in construction works, it's 100x slower.)
c_char*6
handled, unfortunately, nul-terminated string. switch c_byte*6
instead, lose convenience of initializing strings:
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)
output:
97 98 99 (expect: 97 98 99) 97 0 99 (expect: 97 0 99)
python python-2.7 ctypes
No comments:
Post a Comment