рекурсивные структуры python ctype - PullRequest
8 голосов
/ 04 августа 2009

Я разработал DLL для драйвера в C. Я написал тестовую программу на C ++, и DLL работает нормально.

Теперь я бы хотел взаимодействовать с этой DLL, используя Python. Я успешно скрыл большинство пользовательских структур C, но есть один момент, когда я должен использовать структуры C. Я довольно плохо знаком с Python, поэтому могу ошибаться.

Мой подход состоит в том, чтобы переопределить несколько структур в python с использованием ctype, а затем передать переменную в мою DLL. Однако в этом классе у меня есть собственный связанный список, который содержит рекурсивные типы, как следует

class EthercatDatagram(Structure):
    _fields_ = [("header", EthercatDatagramHeader),
                ("packet_data_length", c_int),
                ("packet_data", c_char_p),
                ("work_count", c_ushort),
                ("next_command", EthercatDatagram)]

Это невозможно, поскольку внутри EthercatDatagram EthercatDatagram еще не определена, поэтому анализатор возвращает ошибку.

Как мне представить этот связанный список в python, чтобы моя DLL правильно его понимала?

Ответы [ 3 ]

15 голосов
/ 04 августа 2009

Вы почти наверняка захотите объявить next_command в качестве указателя. Иметь структуру, которая содержит себя, невозможно (на любом языке).

Я думаю, это то, что вы хотите:

class EthercatDatagram(Structure):
    pass
EthercatDatagram._fields_ = [
    ("header", EthercatDatagramHeader),
    ("packet_data_length", c_int),
    ("packet_data", c_char_p),
    ("work_count", c_ushort),
    ("next_command", POINTER(EthercatDatagram))]
0 голосов
/ 24 июля 2013

Причина, по которой

EthercatDatagram._fields_.append(("next_command", EthercatDatagram))

не работает из-за того, что механизм, создающий объекты дескриптора (см. Источник функции PyCStructType_setattro) для доступа к атрибуту next_command, активируется только после назначения к атрибуту _fields_ класса. Простое добавление нового поля в список совершенно незаметно.

Чтобы избежать этой ловушки, всегда используйте кортеж (а не список) в качестве значения атрибута _fields_: это прояснит, что вы должны назначить новое значение атрибуту, а не изменять его на месте .

0 голосов
/ 04 августа 2009

Вам нужно будет получить статический доступ к _fields_ после того, как вы его создали.

class EthercatDatagram(Structure)
  _fields_ = [...]

EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...