2012-08-27 5 views
6

Ich habe eine C-Datei, die eine Reihe von #defines für Bits enthält, die ich von Python referenzieren möchte. Es gibt genug davon, dass ich sie lieber nicht in meinen Python-Code kopieren möchte, gibt es stattdessen eine akzeptierte Methode, um sie direkt von Python aus zu referenzieren?Wie kann ich #defines in einer C-Datei von Python referenzieren?

Hinweis: Ich weiß, ich kann einfach die Header-Datei öffnen und analysieren, das wäre einfach, aber wenn es eine mehr pythonische Art ist, würde ich es gerne verwenden.

Edit:

Diese sind sehr einfach #defines, die die Bedeutungen der Bits in einer Maske, zum Beispiel definieren:

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

möglich Duplikat [Reliably C Präprozessormakros zu Python-Code Umwandlung] (http://stackoverflow.com/questions/2654329/reliably-converting-c-preproce ssor-macros-to-python-code) –

+0

Ich denke, das ist ein Duplikat zu http://stackoverflow.com/questions/2654329/reliably-converting-c-preprocessor-macros-to-python-code –

+1

@ MattiLyra - Vielleicht . Aber da diese Frage derzeit keine Antworten hat, ist dies kein besonders hilfreicher Punkt. –

Antwort

3

Wird unter der Annahme ausgeführt, dass die C .h-Datei nur #defines enthält (und daher nichts mit externem Link zu verknüpfen ist), dann würde Folgendes mit swig 2.0 (http://www.swig.org/) funktionieren Python 2.7 (getestet). Angenommen, die Datei nur enthält, definiert ist benannt just_defines.h wie oben:

#define FOO_A 0x3 
#define FOO_B 0x5 

Dann:

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 

Verbrauch:

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

Wenn die .h-Datei auch Einstiegspunkte enthält, dann Sie müssen eine Verbindung zu einer Bibliothek (oder mehreren) herstellen, um diese Einstiegspunkte zu beheben. Das macht die Lösung ein wenig komplizierter, da Sie möglicherweise die richtigen Bibliotheken suchen müssen. Aber für einen "klar definierten Fall" müssen Sie sich keine Sorgen machen.

+0

Diese Methode hat super funktioniert! Ich muss entscheiden, ob es sich lohnt, etwas einfaches C zu schreiben, um mit diesem Header zu interagieren. Es könnte einfach einfacher sein, was ich brauche, um den C-Header von Hand zu parsen. – mfisch

1

#define s sind Makros, die keinerlei Bedeutung außerhalb Ihrer C haben Compiler-Präprozessor. Als solche sind sie der Fluch der mehrsprachigen Programmierer überall. (Siehe zum Beispiel diese Ada Frage: Setting the license for modules in the linux kernel von vor zwei Wochen).

Kurz von Ihrem Quellcode über den C-Präprozessor laufen, gibt es wirklich keinen guten Weg, damit umzugehen. Normalerweise finde ich heraus, worüber sie auswerten (in komplexen Fällen, oft gibt es keinen besseren Weg, dies zu tun, als den verdammten Code tatsächlich zu kompilieren und auszuführen!), Und diesen Wert in mein Programm zu schreiben.

Der (wohl eine der) ärgerlichen Teile ist, dass der C-Präprozessor von C-Codern als eine sehr einfache kleine Sache angesehen wird, die sie oft benutzen, ohne auch nur einen Gedanken daran zu verschwenden. Als Ergebnis sind sie eher schockiert, dass dies große Probleme für die Interoperabilität verursacht, während wir mit den meisten anderen Problemen umgehen können, die C uns ziemlich leicht zufügt.

In dem einfachen Fall, der oben gezeigt wird, wäre der einfachste Weg, um es zu behandeln, die gleichen zwei Werte in Konstanten in Ihrem Python-Programm irgendwo zu kodieren. Wenn es eine große Sache ist, mit Änderungen Schritt zu halten, wäre es wahrscheinlich nicht allzu schwierig, ein Python-Programm zu schreiben, um diese Werte aus der Datei zu analysieren. Allerdings müssten Sie erkennen, dass Ihr C-Code diese Werte nur bei einer Kompilierung neu bewerten würde, während Ihr Python-Programm es immer ausführen würde (und daher wahrscheinlich nur ausgeführt werden sollte, wenn der C-Code ebenfalls kompiliert wird).

+0

Ich denke für viele Leute wird die einfache Methode, die Sie vorgeschlagen haben, funktionieren entweder Parsing der Header oder Führen der #defines in einen Editor und Suchen/Ersetzen, um sie in Python-Consts zu übersetzen, abhängig davon, wie oft der Header ändern könnte. – mfisch

3

Sie könnten etwas Glück mit dem Skript h2py.py im Verzeichnis Tools/scripts des Python-Quell-Tarballs haben. Es kann zwar keine komplexen Präprozessormakros verarbeiten, reicht jedoch für Ihre Anforderungen aus.

Hier ist eine Beschreibung der Funktionalität von dem Anfang des Skripts:

lesen # die definieren und zu Python-Code übersetzen. Handle # include-Anweisungen. Handle #define Makros mit einem Argument. Alles, was nicht erkannt wird oder nicht in gültiges Python übersetzt wird ignoriert.

Ohne Argumente für Dateinamen, fungiert als Filter. Wenn ein oder mehrere Dateinamen angegeben werden, wird die Ausgabe in die entsprechenden Dateinamen im lokalen Verzeichnis geschrieben und in Großbuchstaben übersetzt, wobei die Erweiterung durch ".py" ersetzt wird.

Durch die Übergabe einer oder mehrerer Optionen der Form "-i regulärer_Ausdruck" können Sie zusätzliche Zeichenfolgen angeben, die ignoriert werden sollen. Dies ist nützlich z.B. Umgüsse auf u_long zu ignorieren: gib einfach "-i '(u_long)'" an.

0

Ich hatte fast genau das gleiche Problem eine Python-Skript, so schrieb die C-Datei zu analysieren. Es soll umbenannt werden, damit es mit Ihrer c-Datei übereinstimmt (aber mit .py anstelle von .h) und als Python-Modul importiert wird.

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

Beispiel:

configuration.h

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

Verwendung von 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