2010-01-12 13 views
12

A menudo tengo que escribir código en otros idiomas que interactúan con las estructuras C. Lo más habitual es que esto implique escribir código Python con los módulos struct o ctypes.Extraiga los campos de una estructura C

Así que tendré un archivo .h lleno de definiciones de estructura, y tengo que leerlos manualmente y duplicar esas definiciones en mi código de Python. Esto lleva mucho tiempo y es propenso a errores, y es difícil mantener las dos definiciones sincronizadas cuando cambian con frecuencia.

¿Hay alguna herramienta o biblioteca en cualquier idioma (no tiene que ser C o Python) que pueda tomar un archivo .h y producir una lista estructurada de sus estructuras y sus campos? Me encantaría poder escribir un script para generar mi generación automática de definiciones de estructuras en Python, y no quiero tener que procesar código C arbitrario para hacerlo. Las expresiones regulares funcionarían bien aproximadamente el 90% del tiempo y luego causarían dolores de cabeza sin fin para el 10% restante.

+3

"Las expresiones regulares funcionarían bien el 90% del tiempo y causarían dolores de cabeza interminables para el 10% restante". Es un buen resumen de expresiones regulares. Excepto que haría las proporciones sobre 50/50. – captncraig

Respuesta

10

Si compila su código C con depuración (-g), pahole (git) puede darle los diseños de estructura exactos que se utilizan.

 
$ 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 */ 
}; 
… 

Esto debería ser mucho más agradable para analizar que C.

0

Uno de mis amigos para esta tareas hecho C-analizador que utiliza con el engranaje.

3

Eche un vistazo a Swig o SIP que generaría un código de interfaz para usted o use ctypes.

5

Las expresiones regulares rectas trabajaría grande alrededor del 90% de las veces y luego causar dolores de cabeza sin fin para el 10% restante.

Los dolores de cabeza suceden en los casos en que el código C contiene sintaxis que usted no pensó al escribir sus expresiones regulares. Luego vuelves y te das cuenta de que C no puede ser analizado por expresiones regulares, y la vida no es divertida.

Intenta darle la vuelta: definir su propio formato sencillo, lo que permite menos trucos que C hace, y generar tanto el archivo de cabecera C y el código de la interfaz de Python desde su archivo:

define socketopts 
    int16 port 
    int32 ipv4address 
    int32 flags 

A continuación, puede fácilmente escribir algo de Python para convertir esto en:

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

y también para emitir una clase Python que utiliza struct para empacar/desempacar tres valores (posiblemente dos de ellos big endian y el otro ascendente hacia la izquierda nativa, depende de usted) .

+0

Definitivamente lo he considerado, pero a menudo recibimos código de otra empresa con la que necesitamos implementar un protocolo personalizado para comunicarnos, y dado que no podemos reescribir su código pero sí tener acceso a sus archivos de encabezado, este enfoque no es es factible Sin embargo, si estuviera implementando un sistema con componentes C y Python desde el principio, definitivamente haría esto. –

+0

Además, me acabo de dar cuenta de que mi ejemplo sigue siendo bastante horrible, ya que el código de Python necesita tener en cuenta el relleno dependiente de la plataforma entre "puerto" e "dirección IPv4". Tal vez podría dirigirse a "propenso a errores" teniendo este esquema, traduciendo manualmente los encabezados a la DSL, y luego autogenerando algunas pruebas (escritas en C) que aseguran que su estructura y la estructura original son idénticas, al escribir valores específicos a los diversos campos de ambas estructuras y luego memcmping ellos. Luego prueba el código de Python de la misma manera. Si todas las coincidencias, estás bien. –

+1

... si su tercero le envía un archivo de encabezado que no puede traducir a su DSL, entonces extienda el DSL o si no se queje ;-) Pero prefiero la respuesta de ephemient, seguramente será mucho menos trabajo, si solo porque toda la información de relleno se saca directamente del compilador. –

1

He usado con bastante éxito GCCXML en proyectos bastante grandes. Obtiene una representación XML del código C (incluidas las estructuras) que puede postprocesar con Python simple.

1

ctypes-codegen o ctypeslib (lo mismo, creo) generará ctypes Structure definiciones (también otras cosas, yo creo, pero yo sólo probamos estructuras) mediante el análisis de los archivos de cabecera utilizando GCCXML. Ya no es compatible, pero es probable que funcione en algunos casos.

Cuestiones relacionadas