2012-12-14 120 views
2

我希望能夠使用ctypes python模塊從python使用C/C++函數。共享庫符號名稱

我在.c/.cpp文件中有一個功能int doit()。當我嘗試加載共享庫:

Frr=CDLL("/path/FoCpy2/libFrr.so") 
Frr.doit(c_int(5)) 

我覺得它的工作真的很好用的.c變種時。當C++被稱爲好方法調用這個函數(發現使用nm libFrr.so使用nm -gC libFrr.so產生只是普通doit()):

Frr._Z4doitv(c_int(5)) 

我已經在Stackexchange閱讀沒有從蟒蛇調用C++標準的方式,並有「非標準名稱修改」問題。 「Z4」是這個問題的一部分嗎?我猜非標準名稱會出現在更高級的語言特性中,例如類方法,模板,但是對於這樣的基本函數呢?是否可以在C++代碼的簡單情況下強制使用簡單的C函數名稱?

+2

extern「C」{your c API} in your header file ... – neagoegab

+0

你應該看看[swig實用工具](http://www.swig.org/),特別是[C++/python支持部分](http://www.swig.org/Doc1.3/Python.html) – didierc

回答

2

您可以使用extern "C"將功能「看起來像」C函數向外界(即禁用名稱修改)。是的,你是正確的,名稱修改主要用於C++所具有的更復雜功能和類型的功能,並且名稱修改方案從未標準化(也不是二進制兼容性),所以它因編譯器而異和版本之間(但大多數主流編譯器現在已經解決了一些問題,但編譯器供應商之間仍然存在差異)。而且舊的免費函數也需要修改的原因是因爲C++支持重載(相同的函數名稱但具有不同的參數),因此編譯器會將參數規範(例如類型)編碼爲重名的名稱。當然,如果你使用extern "C",你會失去所有需要修改名稱的特性,所以它或多或少歸結爲C函數。

您可以使用extern "C"無論是在每個功能的基礎上,像這樣:

extern "C" int doit(); 

或爲整體頭部:

extern "C" { 

// all the function declarations here ... 

}; 

然而,爲Python具體而言,我強烈建議您使用一個庫,它允許你構建Python類和函數,它們反映了你的C++類和函數,這使得生活變得更加簡單,並且隱藏了所有這些外部「C」業務。我推薦使用Boost.Python,看到這個getting started page,它使得向Python導出函數和類變得輕而易舉。我猜別人也會推薦SWIG,但我從來沒有用過它。

+0

認爲這兩個答案。 Boost.Python似乎非常充足。再想一想。 – Lacek

2

調用C++庫函數總是很亂,實際上即使你使用的是C++,你也必須使用相同的編譯器等來確保它的正常工作。

唯一的一般解決方案是將您的C++函數定義爲extern "C"並確保您遵循所涉及的限制 - 請參閱here以獲得解釋。