作為Python程序員,應該能夠正視Python的優點與缺點。眾所周之,Python的運行速度是很慢的,特別是大數據量的運算時,Python會慢得讓人難以忍受。對于這種情況,“專業”的解決方案是用上numpy或者opencl。不過有時候為了一點小功能用上這種重型的解決方案很不劃算,或者有時候想要實現的操作在numpy里面沒有,需要我們自己用C語言來編寫。總之,我們使用Python與C++的混合編程能夠加快程序熱點的運算速度。
首先要提醒大家注意的是,在考慮聯合編程之前一定要找到程序運行的熱點。簡單一點地,使用標準庫的profile或者cProfile模塊找到最消耗CPU的位置,如果這個位置只簡單的消耗IO時間,通常換成C++程序的意義也不會很大,此時做聯合編程可能是事倍功半,起不到多大的效果。
還有些情況,Python程序員們想要使用操作系統或者外部模塊提供的函數。這些模塊一般是為C/C++程序員提供的。這時候也是Python與C++聯合編程的用武之地。
Python語言可以說是最好的膠水語言。僅就與C++聯合編程這個問題來講,依使用難度與功能來排列,Python社區提供了以下幾種解決方案:
1.使用標準庫ctypes直接調用C/C++編寫的動態鏈接庫。這是最簡單易用的方案。C/C++程序員使用自己的豐富的經驗,把預定的功能實現為動態鏈接庫。而Python程序員只要知道這些動態鏈接庫函數的名稱、參數類型與返回值類型就能簡單地調用它。當你傳入參數時,ctypes模塊會自動地把Python的對象成為C/C++所對應的參數類型。比如以下調用Windows的API:
#定義參數類型與函數名稱 from ctypes.wintypes import UINT, DWORD GetLastInputInfo = ctypes.windll.user32.GetLastInputInfo class LASTINPUTINFO(ctypes.Structure): _fields_ = [("cbSize", UINT), ("dwTime", DWORD)] #開始調用DLL導出的函數 def getLastInputTime_nt(): info = LASTINPUTINFO() info.cbSize = ctypes.sizeof(info) info.dwTime = 0 if not GetLastInputInfo(ctypes.byref(info)): raise WindowsError("") return info.dwTime
在這里展示了如何構造Windows的API所需要的結構體,如何填充結構體并分析返回值。
ctypes還能將Python函數提供給C/C++代碼作為回調函數。
與其它解決方案相比。ctypes不需要程序員熟悉C/C++語言,不需要安裝一個C/C++的編譯器,它通過操作系統的接口直接操作C/C++代碼。而且ctypes是標準庫的一部分,只要安裝了Python就可以直接使用。這幾個原因使得它深受Python程序員的喜愛。
而它的劣勢呢。首先,ctypes不能簡單調用C++程序,因為C++在編譯的時候使用了name mangling這個技術來實現函數的重載。C++會自動地為類的成員函數加上類名前綴。所以,C++程序員需要以C語言的調用約定來提供接口,沒有類,沒有重載函數,沒有模板,沒有C++異常。不能直接調用現有的C++代碼可能是這個方案最大的缺點。
新聞熱點
疑難解答