2012-08-27 13 views
6

Mam plik C, który ma kilka #defines dla bitów, które chciałbym odwołać się z Pythona. Jest ich wystarczająco dużo, że wolałbym nie kopiować ich do mojego kodu Pythona, zamiast tego istnieje akceptowana metoda odwoływania się do nich bezpośrednio z Pythona?Jak mogę odwołać się do # definicje w pliku C z Pythona?

Uwaga: Wiem, że mogę po prostu otworzyć plik nagłówkowy i przetworzyć go, byłoby to proste, ale jeśli jest bardziej pythonic, chciałbym go użyć.

Edit:

Są to bardzo proste #defines które definiują znaczenie bitów w masce, na przykład:

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

możliwe duplikat [niezawodnie konwersji makr preprocesora C kodu pytona] (http://stackoverflow.com/questions/2654329/reliably-converting-c-preproce ssor-macros-to-python-code) –

+0

Myślę, że jest to duplikat http://stackoverflow.com/questions/2654329/reliably-converting-c-preprocessor-macros-to-python-code –

+1

@MattiLyra - Być może . Jednak obecnie, gdy to pytanie nie ma odpowiedzi, nie jest to szczególnie pomocne. –

Odpowiedz

3

Działa przy założeniu, że plik C.h zawiera tylko #definy (i dlatego nie ma nic zewnętrznego do połączenia z), a następnie będzie działać z plikiem swig 2.0 (http://www.swig.org/) i python 2.7 (testowany). Załóżmy, że plik zawierający tylko definiuje nazwie just_defines.h jak wyżej:

#define FOO_A 0x3 
#define FOO_B 0x5 

Następnie:

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 

Zastosowanie:

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

Jeśli plik .h zawiera również punkty wejścia, a następnie musisz połączyć się z pewną biblioteką (lub więcej), aby rozwiązać te punkty wejścia. To sprawia, że ​​rozwiązanie jest nieco bardziej skomplikowane, ponieważ może być konieczne wyszukiwanie właściwych bibliotek. Ale dla "sprawiedliwego definiowania sprawy" nie musisz się o to martwić.

+0

Ta metoda działała świetnie! Muszę zdecydować, czy warto napisać proste C do interfejsu z tym nagłówkiem. Może być prostsze, jeśli chodzi o to, czego potrzebuję do ręcznego analizowania nagłówka C. – mfisch

1

#define s są makra, które nie mają znaczenia w ogóle spoza C preprocesor kompilatora. Jako takie, są one zmorą wielu programistów w wielu językach. (Na przykład zobacz to pytanie Ada: Setting the license for modules in the linux kernel sprzed dwóch tygodni).

Brak uruchamiania kodu źródłowego przez preprocesor C, tak naprawdę nie ma dobrego sposobu na poradzenie sobie z nimi. Zwykle po prostu wymyślam, do czego się odnoszą (w skomplikowanych przypadkach, często nie ma lepszego sposobu na to, niż faktyczne skompilowanie i uruchomienie tego cholernego kodu!), I zakodowanie tego kodu do mojego programu.

(dobrze jedna z) denerwujących części jest to, że preprocesor C jest uważany przez koderów C za bardzo prostą małą rzecz, której często używają, nawet nie zastanawiając się dłużej. W rezultacie, są zszokowani, ponieważ powoduje to duże problemy z interoperacyjnością, podczas gdy możemy poradzić sobie z większością innych problemów, które C rzuca na nas dość łatwo.

W prostym przykładzie pokazanym powyżej, zdecydowanie najprostszym sposobem na obsłużenie go byłoby zakodowanie tych samych dwóch wartości stałych w programie Pythona gdzieś. Jeśli nadążanie za zmianami to wielka sprawa, prawdopodobnie nie byłoby zbyt wielkim problemem napisanie programu w języku Python, aby przeanalizować te wartości z pliku. Musisz jednak zdać sobie sprawę, że twój kod C będzie tylko ponownie oceniał te wartości podczas kompilacji, podczas gdy twój program pythona działałby po uruchomieniu (i prawdopodobnie powinien być uruchamiany tylko wtedy, gdy kod C jest również kompilowany).

+0

Myślę, że dla wielu osób prosta metoda, którą zasugerowałeś, będzie działała, parsując nagłówek lub prowadząC#defines do edytora i wykonując search/replace, aby przetłumaczyć je na python consts, w zależności od tego, jak często nagłówek może się zmieniać. – mfisch

3

Może masz trochę szczęścia ze skryptem h2py.py znalezionym w katalogu Tools/scripts w archiwum źródeł Pythona. Chociaż nie może obsłużyć złożonych makr preprocesorów, może być wystarczający dla twoich potrzeb.

Oto opis funkcjonalność od początku skryptu:

lektura #define i przełożyć do kodu Pythona. Obsługa instrukcji #include. Obsługa makr #define za pomocą jednego argumentu. Wszystko, co nie jest rozpoznawane lub nie jest tłumaczone na prawidłowy Python jest ignorowane.

Bez argumentów nazwy pliku działa jako filtr. Jeśli podano jedną lub więcej nazw plików, dane wyjściowe są zapisywane w odpowiednich nazwach plików , przetłumaczonych na wielkie litery, z rozszerzeniem na ".py".

Podając jedną lub więcej opcji formularza "-i regular_expression" można określić dodatkowe ciągi do zignorowania. Jest to przydatne np. zignorować rzuty na u_long: po prostu podaj "-i" (u_long) "".

0

miałem niemal dokładnie ten sam problem, więc napisałem skrypt Pythona do analizowania pliku C. Jego nazwa ma zostać zmieniona tak, aby pasowała do twojego pliku c (ale z rozszerzeniem .py zamiast .h) i importowana jako moduł Pythona.

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

przykład:

configuration.h

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

Korzystanie z Pythonie

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