I want to create ctypes.Structure-like object from bytes with Object(bytes_buffer)-like pattern.
According to https://stackoverflow.com/a/11486058 I use __new__ factory
from ctypes import Structure, c_char, c_uint8
ARRAY_LENGTH = 5
class Person(Structure):
_fields_ = [("name", c_char * ARRAY_LENGTH),
("age", c_uint8)]
def __new__(cls, buf):
return cls.from_buffer_copy(buf)
When calling Structure.from_buffer_copy it looks like the method doesn't check the \0 character (and it looks like Python-style)
>>> p = Person.from_buffer_copy(b"Piter\x10")
>>> print(p.name, p.age)
... b'Piter' 16
But when calling from_buffer_copy from Structure.__new__ the method checks \0 character when interpreting c_char * 5 (and it looks like C-style)
>>> p = Person(b"Piter\x10")
Traceback (most recent call last):
File "/home/denis/person.py", line 69, in <module>
p = Person(b"Piter\x10")
ValueError: bytes too long (6, maximum length 5)
But using C-style string works well in both cases:
ARRAY_LENGTH = 6
class Person(Structure):
_fields_ = [("name", c_char * ARRAY_LENGTH),
("age", c_uint8)]
def __new__(cls, buf):
return cls.from_buffer_copy(buf)
>>> p = Person.from_buffer_copy(b"Piter\0\x10")
>>> print(p.name, p.age)
... b'Piter' 16
>>> p = Person(b"Piter\0\x10")
>>> print(p.name, p.age)
... b'Piter' 16
So
Person.from_buffer_copy(b"Piter\x10")interprets full array length when\0is not presented.Person(b"Piter\x10")requires the\0.
I have no idea why it's so. Is it Python feature?
I run code with both Python 2 and Python 3
Python 3.8.5 (default, Sep 4 2020, 07:30:14)
[GCC 7.3.0] on linux
and
Python 2.7.18 (default, Aug 4 2020, 11:16:42)
[GCC 9.3.0] on linux2
(used "Piter\x10" instead of b"Piter\x10")