Ctypes: получить указатель на поле структуры - PullRequest
0 голосов
/ 25 мая 2018

Мне нужно получить указатель с адресом структурного поля.Важно: я собираю сериализатор для набора структур c, поэтому хочу перебрать поля структуры и получить адрес каждого из них в качестве указателя.Я знаю, что есть способ использования полей объекта и свойства смещения их, который дает вам смещение от адреса самой структуры, но это общий указатель.Не могли бы вы показать мне способ перебора структурных полей и для каждого из них получить указатель ctypes с правильным внутренним типом?

1 Ответ

0 голосов
/ 25 мая 2018

Вот способ ...

Переменная класса Test._fields_ определяет атрибуты и их типы C.Атрибуты класса, созданные путем назначения полей, содержат информацию о смещении для этого атрибута, например:

>>> Test.a
<Field type=c_long, ofs=0, size=4>
>>> Test.b
<Field type=c_double, ofs=8, size=8>
>>> Test.c
<Field type=c_char_Array_10, ofs=16, size=10>

Для каждого типа метод from_buffer() создает тип C, используя тот же буфер данных, что и существующийтип.Экземпляр структуры реализует буферный API, необходимый для доступа к его данным, поэтому, если вы знаете смещение данных элемента структуры, вы можете сгенерировать тип ctypes, который ссылается на те же данные, и создать указатель на них.

from ctypes import *

class Test(Structure):
    _fields_ = [('a',c_int),
                ('b',c_double),
                ('c',c_char * 10)]

x = Test(1,2.5,b'abc')

for field,ftype in Test._fields_:

    # Look up each attribute in the class, and get its offset.
    ofs = getattr(Test,field).offset

    # Create a pointer to the same field type using the same data.
    p = pointer(ftype.from_buffer(x,ofs))
    print(p,p.contents)

Вывод:

<__main__.LP_c_long object at 0x000001932DE0EEC8> c_long(1)
<__main__.LP_c_double object at 0x000001932DE0ECC8> c_double(2.5)
<__main__.LP_c_char_Array_10 object at 0x000001932DE0EDC8> <__main__.c_char_Array_10 object at 0x000001932DE0ECC8>
...