Domanda

Ho sviluppato una DLL per un driver in C. Ho scritto un programma di test in C ++ e la DLL funziona bene.

Ora vorrei interrompere con questa DLL usando Python. Ho nascosto con successo la maggior parte delle strutture C definite dall'utente, ma c'è un punto in cui devo usare le strutture C. Sono piuttosto nuovo su Python, quindi potrei sbagliare.

Il mio approccio è ridefinire alcune strutture in Python usando ctype quindi passare la variabile alla mia DLL. Tuttavia in questa classe ho un elenco di collegamenti personalizzati che contiene tipi ricorsivi come segue

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

Questo non riesce, perché all'interno di EthercatDatagram, EthercatDatagram non è già definito, quindi il parser restituisce un errore.

Come dovrei rappresentare questo elenco collegato in Python in modo che la mia DLL lo capisca correttamente?

È stato utile?

Soluzione

Quasi sicuramente vuoi dichiarare next_command come puntatore. Non è possibile avere una struttura che contiene se stessa (in qualsiasi lingua).

Penso che questo sia quello che vuoi:

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))]

Altri suggerimenti

Il motivo per cui

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

non funziona è che la macchina che crea gli oggetti descrittori (vedi l'origine di PyCStructType_setattro ) per accedere all'attributo next_command è attivato solo dopo l'assegnazione al _fields_ dell'attributo della classe. L'aggiunta del nuovo campo all'elenco passa completamente inosservata.

Per evitare questa trappola, usa sempre una tupla (e non un elenco) come valore dell'attributo _fields_ : questo chiarirà che devi assegnare un nuovo valore all'attributo e non modificarlo sul posto.

Dovrai accedere _fields_ staticamente dopo averlo creato.

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

EthercatDatagram._fields_.append(("next_command", EthercatDatagram))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top