приведение к массивам в ctypes Python

Я пытаюсь преобразовать 16-байтовый блок данных, возвращаемый socket.inet_pton, в массив ctypes байтов без знака. Моя структура данных выглядит так:

class in6_addr(ctypes.Structure):
    _fields_ = (("Byte", ctypes.c_ubyte * 16),)

И блоб просто:

data = socket.inet_pton(socket.AF_INET6, "2001::3")

Однако эти попытки приводят к ошибкам:

sin6 = in6_addr()

# TypeError: expected c_ubyte_Array_16 instance, got str
sin6.Byte = data
# TypeError: cast() argument 2 must be a pointer type, not c_ubyte_Array_16
sin6.Byte = ctypes.cast(data, ctypes.c_ubyte * 16)
# TypeError: incompatible types, LP_c_ubyte instance instead of c_ubyte_Array_16 instance
sin6.Byte = ctypes.cast(data, ctypes.POINTER(ctypes.c_ubyte))

Весь код: http://codepad.org/2cjyVXBA.

Любые идеи, к какому типу мне нужно привести?


person user334987    schedule 20.07.2010    source источник


Ответы (2)


Я могу ошибаться здесь (и это кажется немного сложным), но это работает для меня:

sin6.Byte = (ctypes.c_ubyte*16)(*list(bytearray(data)))

Мне пришлось преобразовать данные в список целых чисел и распаковать их для конструктора. Должен быть более простой способ!

person Scott Griffiths    schedule 20.07.2010

Возможно проще:

sin6.Byte = cast(data, ctypes.POINTER(ctypes.c_ubyte * 16)).contents

or:

sin6.Byte = (ctypes.c_ubyte * 16)(*[x for x in data])

Использование потока байтов:

import io
io.BytesIO(data).readinto(sin6.Byte)

А так как рассматриваемая структура содержит единственное поле, то имя поля можно не указывать:

sin6 = cast(data, ctypes.POINTER(ctypes.c_ubyte * 16)).contents
sin6 = (ctypes.c_ubyte * 16)(*[x for x in data])
io.BytesIO(data).readinto(sin6)
person Alex    schedule 24.03.2020