2012-08-27 17 views
6

Tengo un archivo C que tiene un montón de #defines para bits a los que me gustaría hacer referencia desde python. Hay suficientes que prefiero no copiarlos en mi código python, ¿hay algún método aceptado para referenciarlos directamente desde Python?¿Cómo puedo hacer referencia a #defines en un archivo C de python?

Nota: Sé que puedo simplemente abrir el archivo de encabezado y analizarlo, eso sería simple, pero si hay una manera más pitonica, me gustaría usarla.

Editar:

Estos son #defines muy simples que definen los significados de los bits en una máscara, por ejemplo:

#define FOO_A 0x3 
#define FOO_B 0x5 
+0

posible duplicado de [confiablemente convertir macros C preprocesador para código Python] (http://stackoverflow.com/questions/2654329/reliably-converting-c-preproce ssor-macros-to-python-code) –

+0

Creo que este es un duplicado de http://stackoverflow.com/questions/2654329/reliably-converting-c-preprocessor-macros-to-python-code –

+1

@MattiLyra - Tal vez . Pero dado que esa pregunta no tiene respuestas actualmente, este no es un punto particularmente útil. –

Respuesta

3

Corriendo bajo el supuesto de que el archivo C .h contiene solo #defines (y por lo tanto no tiene nada externo para vincular), entonces lo siguiente funcionaría con swig 2.0 (http://www.swig.org/) y Python 2.7 (probado). Supongamos que el archivo que contiene se define simplemente se llama just_defines.h que el anterior:

#define FOO_A 0x3 
#define FOO_B 0x5 

continuación:

swig -python -module just just_defines.h ## generates just_defines.py and just_defines_wrap.c 
gcc -c -fpic just_defines_wrap.c -I/usr/include/python2.7 -I. ## creates just_defines_wrap.o 
gcc -shared just_defines_wrap.o -o _just.so ## create _just.so, goes with just_defines.py 

Uso:

$ python 
Python 2.7.3 (default, Aug 1 2012, 05:16:07) 
[GCC 4.6.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import just 
>>> dir(just) 
['FOO_A', 'FOO_B', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_just', '_newclass', '_object', '_swig_getattr', '_swig_property', '_swig_repr', '_swig_setattr', '_swig_setattr_nondynamic'] 
>>> just.FOO_A 
3 
>>> just.FOO_B 
5 
>>> 

Si el archivo .h también contiene puntos de entrada, a continuación, necesita vincular una biblioteca (o más) para resolver esos puntos de entrada. Eso hace que la solución sea un poco más complicada, ya que es posible que tengas que buscar las librerías correctas. Pero para un "caso de definición justa" no tiene que preocuparse por esto.

+0

¡Este método funcionó muy bien! Sin embargo, tengo que decidir si vale la pena el tiempo para escribir algunas C simples para interactuar con este encabezado. Simplemente podría ser más simple para lo que necesito para analizar el encabezado C a mano. – mfisch

1

#define s son macros, que no tienen significado alguno fuera de su C el preprocesador del compilador Como tales, son la ruina de los programadores multilingües en todas partes. (Por ejemplo, vea esta pregunta de Ada: Setting the license for modules in the linux kernel de hace dos semanas).

Si no ejecuta su código fuente a través del preprocesador C, realmente no hay una buena manera de manejarlo. Normalmente solo averiguo a qué evalúan (en casos complejos, a menudo no hay mejor manera de hacerlo que compilar y ejecutar el maldito código), y codificar ese valor en mi programa.

La (bueno) una de las partes molestas es que el preprocesador C es considerado por los codificadores C como una cosa muy simple que a menudo usan sin siquiera pensarlo dos veces. Como resultado, tienden a sorprenderse porque causa grandes problemas para la interoperabilidad, mientras que nosotros podemos lidiar con la mayoría de otros problemas que C nos lanza con bastante facilidad.

En el caso simple que se muestra arriba, con mucho, la forma más fácil de manejarlo sería codificar los mismos dos valores en constantes en su programa de Python en alguna parte. Si mantenerse actualizado con los cambios es un gran problema, probablemente no sería demasiado problema escribir un programa de Python para analizar esos valores fuera del archivo. Sin embargo, tendrías que darte cuenta de que tu código C solo volvería a evaluar esos valores en una compilación, mientras que tu programa python lo haría cada vez que se ejecute (y por lo tanto, probablemente solo debería ejecutarse cuando el código C también esté compilado).

+0

Creo que para muchas personas el método simple que sugirieron funcionará, ya sea analizar el encabezado o llevar las definiciones # a un editor y hacer búsqueda/reemplazo para traducirlas a consteciones de python, dependiendo de qué tan a menudo cambie el encabezado. – mfisch

3

Puede tener algo de suerte con la secuencia de comandos h2py.py que se encuentra en el directorio Tools/scripts del paquete de archivos fuente de Python. Si bien no puede manejar macros complejas de preprocesador, podría ser suficiente para sus necesidades.

Aquí es una descripción de la funcionalidad de la parte superior de la secuencia de comandos:

Leer #define de y traducen a código Python. Manejar #include declaraciones. Manejar #define macros con un argumento. Todo lo que no se reconoce o no se traduce en válido, se ignora.

Sin argumentos de nombre de archivo, actúa como un filtro. Si se dan uno o más nombres de archivo, la salida se escribe en los nombres de archivo correspondientes en el directorio local, traducidos a mayúsculas, con la extensión reemplazada por ".py".

Al pasar una o más opciones de la forma "-i expresión_regular" puede especificar cadenas adicionales que se ignorarán. Esto es útil p. ignorar moldes a u_long: simplemente especifica "-i '(u_long)'".

0

tenía casi exactamente el mismo problema por lo que escribió un script en Python para analizar el archivo C. Se pretende cambiar el nombre para que coincida con su archivo c (pero con .py en lugar de .h) y se importa como un módulo de Python.

Código: https://gist.github.com/camlee/3bf869a5bf39ac5954fdaabbe6a3f437

Ejemplo:

configuration.h

#define VERBOSE 3 
#define DEBUG 1 
#ifdef DEBUG 
    #define DEBUG_FILE "debug.log" 
#else 
    #define NOT_DEBUGGING 1 
#endif 

Uso de Python:

>>> import configuration 
>>> print("The verbosity level is %s" % configuration.VERBOSE) 
The verbosity level is 3 
>>> configuration.DEBUG_FILE 
'"debug.log"' 
>>> configuration.NOT_DEBUGGING is None 
True 
Cuestiones relacionadas