Вопрос по recursion, structure, python, dll, ctypes – рекурсивные структуры python ctype

8

Я разработал 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

Вы почти наверняка захотите объявить 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))]
ISN»возможно (на любом языке) - тот'верно в отношении структур или классов в стиле c / c ++ / java, но в языках с алгебраическими типами данных это 'это не просто возможно, но и очень распространено. напримерdata List a = Cons a (List a) | Nil на языках семейства ML (ocaml / haskell / SML / и т. д.). sinelaw
0

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

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

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

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

-1

Вы'придется получить доступ_fields_ статически после тебямы создали это.

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

EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
Ниже приведен правильный ответ, опубликованный пользователем9876. Сначала вы должны объявить класс с помощью 'проходить'затем объявите поля во втором вызове. Думайте об этом как о предварительной декларации. bpescatore
Это нет работа. Он компилируется и запускается, но попытка использовать экземпляр класса приводит к ошибке: AttributeError: 'EthercatDatagram» объект не имеет атрибутаNEXT_COMMAND» user9876

Похожие вопросы