2010-01-12 32 views
12

Spesso devo scrivere codice in altre lingue che interagiscono con le strutture C. Solitamente questo comporta la scrittura di codice Python con i moduli struct o ctypes.Estrarre i campi di una struttura C

Quindi avrò un file .h pieno di definizioni di struct, e devo leggerlo manualmente e duplicare queste definizioni nel mio codice Python. Questa operazione richiede molto tempo ed è soggetta a errori, ed è difficile mantenere sincronizzate le due definizioni quando cambiano di frequente.

C'è qualche strumento o libreria in qualsiasi lingua (non deve essere C o Python) che può prendere un file .h e produrre un elenco strutturato delle sue strutture e dei loro campi? Mi piacerebbe essere in grado di scrivere uno script per generare automaticamente le mie definizioni di struct in Python, e non voglio dover elaborare un codice C arbitrario per farlo. Le espressioni regolari funzionerebbero alla grande circa il 90% delle volte e quindi causerebbero mal di testa senza fine per il restante 10%.

+3

"Le espressioni regolari funzionerebbero alla grande circa il 90% delle volte e quindi causerebbero mal di testa senza fine per il restante 10%." È un sommario piuttosto buono di espressioni regolari. Tranne che avrei fatto i rapporti su 50/50. – captncraig

risposta

10

Se si compila il codice C con il debug (-g), pahole (git) è possibile fornire i layout esatti della struttura utilizzati.

 
$ pahole /bin/dd 
… 
struct option { 
     const char *    name;     /*  0  8 */ 
     int      has_arg;    /*  8  4 */ 

     /* XXX 4 bytes hole, try to pack */ 

     int *      flag;     /* 16  8 */ 
     int      val;     /* 24  4 */ 

     /* size: 32, cachelines: 1, members: 4 */ 
     /* sum members: 24, holes: 1, sum holes: 4 */ 
     /* padding: 4 */ 
     /* last cacheline: 32 bytes */ 
}; 
… 

Questo dovrebbe essere un bel po 'più bello per analizzare di rette C.

0

Un mio amico per questo compito ha fatto un parser C che usa con l'ingranaggio.

3

Dai uno sguardo a Swig o SIP che genererebbe il codice di interfaccia per te o utilizza ctypes.

5

Le espressioni regolari sarebbe grande lavoro circa il 90% del tempo e quindi causare mal di testa senza fine per il restante 10%.

Il mal di testa si verifica nei casi in cui il codice C contiene la sintassi a cui non avevate pensato durante la scrittura delle espressioni regolari. Poi torni indietro e capisci che C non può essere realmente analizzato da espressioni regolari e la vita non diventa divertente.

Provare a girare intorno: definire il proprio formato di semplice, che permette meno trucchi di C fa, e generare sia il file di intestazione C e il codice di interfaccia Python dal file:

define socketopts 
    int16 port 
    int32 ipv4address 
    int32 flags 

allora si può facilmente scrivere qualche Python per convertire questo:

typedef struct { 
    short port; 
    int ipv4address; 
    int flags; 
} socketopts; 

e anche per emettere una classe Python che usa struct mettere in valigia/decomprimere tre valori (forse due di loro big-endian e l'altro nativo-endian, a voi) .

+0

Ho sicuramente preso in considerazione questo, ma spesso ci viene consegnato il codice da qualche altra società che abbiamo bisogno di implementare un protocollo personalizzato per comunicare, e dal momento che non possiamo riscrivere il codice ma avere accesso ai loro file di intestazione, questo approccio non è è fattibile Tuttavia, se stavo implementando un sistema con entrambi i componenti C e Python da zero, lo farei sicuramente. –

+0

Inoltre, ho appena notato che il mio esempio è ancora piuttosto orribile, dal momento che il codice Python deve tenere conto del padding dipendente dalla piattaforma tra "port" e "ipv4address". Potresti forse indirizzare "a rischio di errore" avendo questo schema, traducendo manualmente le intestazioni sul DSL e poi auto-generando alcuni test (scritti in C) che assicurano che la tua struct e la struct originale siano identiche, scrivendo valori specifici ai vari campi di entrambe le strutture e quindi memcmping loro. Quindi prova il codice Python allo stesso modo. Se tutte le partite sono buone. –

+1

... se la tua terza parte ti invia un file di intestazione che non puoi tradurre nella tua DSL, quindi estendi il DSL o altrimenti lamentati ;-) Ma preferisco la risposta di un ephemient, è molto meno lavoro se solo perché tutte le informazioni sul padding vengono estratte direttamente dal compilatore. –

1

Ho utilizzato con successo lo GCCXML su progetti abbastanza grandi. Ottieni una rappresentazione XML del codice C (incluse le strutture) che puoi post-elaborare con un semplice Python.

1

ctypes-codegen o ctypeslib (stessa cosa, credo) genererà ctypes Structure definizioni (anche altre cose, credo, ma ho provato solo le strutture) analizzando i file di intestazione utilizzando GCCXML. Non è più supportato, ma probabilmente funzionerà in alcuni casi.

Problemi correlati