2012-08-27 48 views
6

我有一個C文件,有一堆#defines的位,我想從python引用。有足夠的,我寧願不將它們複製到我的Python代碼,而是有一種可接受的方法直接從python引用它們?如何從python引用C文件中的#defines?

注:我知道我可以打開頭文件並解析它,這很簡單,但如果有更多pythonic方式,我想使用它。

編輯:

這些是定義在掩碼位的含義很簡單的#define,例如:

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

可能重複(http://stackoverflow.com/questions/2654329/reliably-converting-c-preproce ssor-macros-to-python-code) –

+0

我認爲這是一個複製到http://stackoverflow.com/questions/2654329/reliably-converting-c-preprocessor-macros-to-python-code –

+1

@MattiLyra - 也許。但目前看到的問題沒有答案,這不是特別有用的一點。 –

回答

3

在假定C.h文件只包含#define(因此沒有任何外部鏈接反對)的情況下運行,那麼以下內容適用於swig 2.0(http://www.swig.org/)和蟒蛇2.7(測試)。假設該文件僅包含定義如上命名just_defines.h:

#define FOO_A 0x3 
#define FOO_B 0x5 

然後:

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 

用法:

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

如果.h文件中還包含入口點,然後你需要鏈接一些庫(或更多)來解決這些入口點。這使得解決方案稍微複雜一點,因爲您可能需要搜索正確的庫。但是對於「剛定義的案例」,您不必擔心這一點。

+0

這種方法效果很好!我需要決定是否值得花時間寫一些簡單的C來與這個頭接口。對於我需要手動解析C頭文件可能會更簡單。 – mfisch

1

#define s爲宏,不具有任何意義你的C之外編譯器的預處理器。因此,它們是世界各地多語言程序員的禍根。 (例如,查看這個Ada問題:兩週前的Setting the license for modules in the linux kernel)。

通過C預處理器運行您的源代碼的缺點,真的沒有好方法來處理它們。我通常只是弄清楚他們所評估的是什麼(在複雜的情況下,通常沒有更好的方法來完成這個任務,而不是真正編譯和運行該死的代碼!),以及對我的程序有價值的硬編碼。

令人討厭的部分之一是C預處理器被C編碼器認爲是一個非常簡單的小東西,他們經常使用,甚至沒有給出第二個想法。因此,他們傾向於對互操作性造成重大問題感到震驚,而我們可以很容易地處理大多數其他問題。

在上面所示的簡單情況下,到目前爲止,處理它的最簡單的方法是將常量中的相同的兩個值編碼到某處的python程序中。如果要跟上變化是一件大事,那麼編寫一個Python程序來解析這些值就可能不會太麻煩。然而,你必須認識到你的C代碼只會在編譯時重新評估這些值,而你的python程序會在它運行時執行它(因此應該只在C代碼編譯時運行)。

+0

我認爲對於很多人來說,你建議的簡單方法可以工作,不管是解析頭文件還是將#define引導到編輯器中,並根據頭文件可能更改的頻率進行搜索/替換,將其轉換爲Python常量。 – mfisch

3

您可能會對Python源碼tarball的Tools/scripts目錄中的h2py.py腳本有一些好運。雖然它無法處理複雜的預處理器宏,但它可能足以滿足您的需求。

這裏的功能從腳本的頂部的說明:

閱讀#定義的,並翻譯成Python代碼。 處理#include語句。 使用一個參數處理#define宏。 任何未被識別或沒有被轉換爲有效的東西 Python被忽略。

沒有文件名參數,充當過濾器。 如果給出一個或多個文件名,則將輸出寫入本地目錄中對應的 文件名,並將其翻譯爲全部大寫,並將 的擴展名替換爲「.py」。

通過傳遞格式「-i regular_expression」 中的一個或多個選項,您可以指定要忽略的其他字符串。這是有用的,例如 ,例如忽略轉換爲u_long:只需指定「-i」(u_long)'「。

0

我不得不幾乎完全同樣的問題所以寫了一個Python腳本解析C文件。它的目的是重新命名爲匹配你的c文件(但是使用.py而不是.h)並導入爲Python模塊。

代碼:https://gist.github.com/camlee/3bf869a5bf39ac5954fdaabbe6a3f437

實施例:

configuration.h

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

在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 
的[可靠轉換C預處理的宏Python代碼]