2012-08-27 7 views
6

Ho un file C che ha un sacco di #definiti per bit che vorrei fare riferimento a python. Ce ne sono abbastanza di quelli che preferirei non copiarli nel mio codice Python, invece c'è un metodo accettato per farvi riferimento direttamente da Python?Come posso fare riferimento a #defines in un file C da python?

Nota: so che posso solo aprire il file di intestazione e analizzarlo, sarebbe semplice, ma se c'è un modo più sontuoso, mi piacerebbe usarlo.

Edit:

Questi sono molto semplici #defines che definiscono i significati dei bit in una maschera, ad esempio:

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

possibile duplicato del [affidabile conversione di macro del preprocessore C da codice Python] (http://stackoverflow.com/questions/2654329/reliably-converting-c-preproce ssor-macros-to-python-code) –

+0

Penso che questo sia un duplicato per http://stackoverflow.com/questions/2654329/reliable-converting-c-preprocessor-macros-to-python-code –

+1

@MattiLyra - Forse . Ma visto che quella domanda al momento non ha risposte, questo non è un punto particolarmente utile. –

risposta

3

L'esecuzione presuppone che il file C .h contenga solo #defines (e quindi non contenga nulla di esterno rispetto al collegamento), quindi quanto segue funzionerebbe con swig 2.0 (http://www.swig.org/) e python 2.7 (testato). Supponiamo che il file contenente solo definisce il nome just_defines.h come sopra:

#define FOO_A 0x3 
#define FOO_B 0x5 

Poi:

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 

Usage:

$ 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 
>>> 

Se il file .h contiene anche punti di ingresso, quindi è necessario collegarsi a una libreria (o più) per risolvere tali punti di ingresso. Ciò rende la soluzione un po 'più complicata dal momento che potrebbe essere necessario scovare le librerie corrette. Ma per un "solo definisce caso" non devi preoccuparti di questo.

+0

Questo metodo ha funzionato alla grande! Devo decidere se vale la pena di scrivere qualche semplice C per interfacciarlo con questa intestazione. Potrebbe essere più semplice per quello che ho bisogno di analizzare l'intestazione C a mano. – mfisch

1

#define s sono le macro, che non hanno alcun significato al di fuori della vostra C preprocessore del compilatore. In quanto tali, sono la rovina dei programmatori multilingue in tutto il mondo. (Ad esempio, vedi questa domanda Ada: Setting the license for modules in the linux kernel di due settimane fa).

A corto di eseguire il codice sorgente tramite il preprocessore C, non c'è davvero un buon modo per gestirli. Di solito capisco solo cosa valgono (nei casi complessi, spesso non c'è modo migliore di farlo se non compilare ed eseguire il dannato codice!), E codificare quel valore nel mio programma.

Il (ben uno dei) fastidiose parti è che il preprocessore C è considerato dai programmatori C come una cosa molto semplice che spesso usano senza nemmeno pensarci. Di conseguenza, tendono a rimanere scioccati dal fatto che causano grossi problemi di interoperabilità, mentre noi possiamo affrontare la maggior parte degli altri problemi che ci si presenta in modo abbastanza semplice.

Nel caso semplice illustrato sopra, il modo più semplice per gestirlo sarebbe quello di codificare gli stessi due valori in costanti nel vostro programma python da qualche parte. Se tenere il passo con le modifiche è un grosso problema, probabilmente non sarebbe troppo difficile scrivere un programma Python per analizzare quei valori fuori dal file. Tuttavia, dovresti capire che il tuo codice C rivaluterebbe solo quei valori su una compilazione, mentre il tuo programma python lo farebbe ogni volta che viene eseguito (e quindi dovrebbe probabilmente essere eseguito solo quando il codice C è anche compilato).

+0

Penso che per molte persone il metodo semplice che hai suggerito funzioni, analizzando l'intestazione o conducendo i #defines in un editor e facendo search/replace per tradurli in consoli python, a seconda di quanto spesso l'intestazione potrebbe cambiare. – mfisch

3

Si potrebbe avere un po 'di fortuna con lo script h2py.py trovato nella directory Tools/scripts del tarball del codice sorgente Python. Sebbene non sia in grado di gestire macro di preprocessore complesse, potrebbe essere sufficiente per le tue esigenze.

Ecco una descrizione delle funzionalità dalla parte superiore dello script:

Leggi # definiscono di e si traducono in codice Python. Gestire le istruzioni #include. Gestisci le macro #define con un argomento. Tutto ciò che non è riconosciuto o che non si traduce in valido Python viene ignorato.

Senza argomenti nomefile, funge da filtro. Se vengono assegnati uno o più nomi di file, l'output viene scritto nei corrispondenti nomi di file nella directory locale, tradotti in maiuscolo, con l'estensione sostituita da ".py".

Passando una o più opzioni del modulo "-i regular_expression" è possibile specificare stringhe aggiuntive da ignorare. Questo è utile ad es. ignorare i cast a u_long: basta specificare "-i '(u_long)'".

0

ho avuto quasi esattamente lo stesso problema così ha scritto uno script Python per analizzare il file C. È destinato a essere rinominato in modo che corrisponda al tuo file c (ma con .py anziché a .h) e importato come modulo Python.

Codice: https://gist.github.com/camlee/3bf869a5bf39ac5954fdaabbe6a3f437

Esempio:

configuration.h

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

Utilizzando da 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 
Problemi correlati