estruturas recursivas pitão Ctype
Pergunta
Eu já desenvolveu um DLL para um motorista em C. Eu escrevi um programa de teste em C ++ eo DLL funciona bem.
Agora, eu gostaria de interract com este DLL usando Python. Eu tenho escondido com sucesso a maioria das estruturas C definidas pelo usuário, mas há um ponto em que eu tenho que usar estruturas C. Eu sou um pouco novo para python para que eu possa fazer as coisas erradas.
A minha abordagem é redefinir algumas estruturas em python usando ctype em seguida, passar a variável para a minha DLL. No entanto nestes classe Eu tenho uma lista ligada personalizado que contém tipos recursiva como segue
class EthercatDatagram(Structure):
_fields_ = [("header", EthercatDatagramHeader),
("packet_data_length", c_int),
("packet_data", c_char_p),
("work_count", c_ushort),
("next_command", EthercatDatagram)]
Esta falha, porque EthercatDatagram dentro, EthercatDatagram ainda não estiver definido de modo que o analisador retorna um erro.
Como devo representar esta lista ligada em python para que a minha DLL entende-lo corretamente?
Solução
Você certamente quer declarar NEXT_COMMAND como um ponteiro. Ter uma estrutura que contém em si não é possível (em qualquer idioma).
Eu acho que isso é o que você quer:
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))]
Outras dicas
A razão pela qual
EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
não funciona é que a máquina que cria os objetos descritor (ver a fonte do PyCStructType_setattro
função) para acessar o atributo next_command
é ativado apenas mediante atribuição para o atributo _fields_
da classe.
Apenas acrescentando o novo campo para a lista continua completamente despercebido.
Para evitar essa armadilha, use sempre um tuple (e não uma lista) como o valor do atributo _fields_
: que vai deixar claro que você tem que atribuir um novo valor para o atributo e não modificá-lo no lugar <. / p>
Você terá acesso _fields_
estaticamente depois de ter criado-lo.
class EthercatDatagram(Structure)
_fields_ = [...]
EthercatDatagram._fields_.append(("next_command", EthercatDatagram))