欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

淺談Python程序與C++程序的聯合使用

系統 1614 0

作為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++代碼可能是這個方案最大的缺點。

??? 另外,對于list, set之類的數據類型,ctypes不能識別并自動地在Python與C/C++數據類型之間轉換。C/C++部分不能識別Python數據類型,這時候只能用Python語言來編寫轉換代碼。如果數據量較大,或者調用很頻繁,轉換代碼反而會浪費很多的資源。這或許是ctypes的另一個劣勢之一了。

2.如果你使用的是Jython或者IronPython的話,它們也提供了類似于ctypes之類的模塊,能夠直接訪問Java或者.Net語言編寫的模塊。其優勢與劣勢大致與ctypes相似。因為其使用范圍有限,這里不再詳述。

3.使用Cython語言,一種類似于Python語言的一種新型語言編寫預定功能的代碼,然后將這些代碼轉換成為C語言編譯成為Python語言可以直接調用的二進制模塊。Cython語言是融合Python語言與C語言的一種新型語言。它本身能夠理解Python語言的語法,然后在其基礎上增加了某些C語言的語法,以便更精細地控制數據類型與指針。基本兼容Python語法是這個解決方案最大的特點。很多時候,Python程序員只要在舊的代碼中簡單地聲明一下代碼中所使用的參數、變量的類型,就能把立即為舊的Python程序提速。

??? Cython提供了一個名為pyximporter的工具,能夠在安裝了C/C++編譯器的計算機上面為簡單的Cython程序直接生成相應的Python模塊。這使得Cython的使用與普通的Python程序一樣簡單。比如下面這段代碼,直接保存為myhello.pyx即可被調用。

            
  #myhello.pyx
  def sayHelloTenTimes():
    cdef int i #只要簡單地為變量標識類型即可加速循環。
    for i in range(0, 10):
      print("hello, world!")

  $ python
  >>> import pyximport; pyximport.install()
  >>> import myhello
  >>> myhello.sayHelloTenTimes()


          

??? 由此可見,Cython非常容易使用。而且不僅能夠處理C語言的模塊,還能處理C++的模塊――雖然沒有直接支持虛函數之類的完整C++特性。因為它不直接使用C/C++語法,而是另外設計比C/C++更簡潔優雅的新型語法,因此,對于不熟悉C/C++的程序員來說有很大的吸引力。相比ctypes來說,因為參數類型轉換更加智能與高效,所以通常能夠提升更多的效率。

??? 劣勢呢,所謂用Python程序員所熟練的語法來編寫高速的運算代碼,乍一聽相當地有吸引力。但是如果想要更深入地控制內存與數據結構時,程序員可能會發現,現在他不得不熟練地掌握C/C++語言,然后用Cython的語法寫出來。以程序員們懶惰的性格,這反而是件難以忍受的事件。這或許是Cython本身并不大流行的主要原因吧。

4.使用boost.python。有意思的是,與ctypes/Cython形成鮮明的對比,boost.python傾向于讓C++程序員擁有更熟悉的編程環境。它讓C++程序員使用他所熟悉的C++語法直接控制Python的數據結構,調用Python的解釋器。它沒有像Cython那樣發明新的語法,而是直接使用C++的語法,編寫供Python使用的接口。與Cython同樣的道理,它的效率優勝于ctypes。

??? 與Cython/SWIG/SIP等方案相比,程序員只需要學習C/C++與Python兩種語言。另外,與本文提到的幾種解決方案相比,它非常適合在主要由C++編寫的程序中控制Python代碼。不僅功能更強大、效率還更高。如此神奇的解決方案會有什么劣勢呢?某些人可能不同意吧,老魚一聽說它依賴于boost就蔫了,感覺編譯與學習龐大又奇怪的boost非常浪費生命。

5.使用SWIG或者SIP,通過編寫一個接口文件,使用類似于C/C++語法――聲明函數、類型的信息,然后使用特殊的工具為C/C++的代碼生成Python的接口代碼。這些接口代碼能夠在Python與C/C++之間的數據結構轉換。最終編譯這些接口代碼,成為Python的二進制模塊。SWIG與SIP的接口文件與C/C++的頭文件非常相似。

??? 這兩種工具差不多,因為。本質上,他們都與Cython類似,都使用了中間語言來生成轉換代碼。但SWIG/SIP能夠在他們的接口文件中嵌入C/C++,能夠讓程序員仔細地調節數據類型的轉換過程。在使用上,它比Cython的層次更低,更接近于Python本身提供的API。

??? SWIG能夠為多種腳本語言生成轉換代碼。而SIP則專門針對Python與C++。此外,SIP本身是作為PyQt的專門工具來開發的,因此它能夠理解Qt的signal/slot。從應用項目上來看,SWIG似乎會更廣泛一點。而SIP,目前所見的項目基本都與PyQt相關。據說SWIG對于C++的支持不好,不知道有沒有人來說一下呢。相比之下,SIP對于C++的支持非常完善,諸如虛函數、protected member function、模版、析構函數、異常等特性都得到良好的支持。而且SIP支持Python的GIL,還擁有一個使用Python編寫的編譯系統。可能會更方便一點。

??? 然而這種方案畢竟要學習一種新的語言,所以從表面上來看不如Cython和boost.python討喜。當程序員想要仔細地調節類型轉換代碼的時候,需要學習SWIG/SIP的內部機制,被限定使用特殊的變量名。這使得這種方案的學習曲線相對較高。

6.直接使用Python的API,可以稱之為最終解決方案。Cython, SWIG, SIP的接口文件轉換后所生成的C/C++代碼實際上都使用Python的API。與其它方案相比,這種方案相當地繁復,必須為每次函數調用編寫數據轉換代碼,還要操心Python對象的引用計數。我覺得這種方案一無是處,這時就不再多講了。其它的工具pybindgen不知道什么情況。有興趣的話可以看看。

好了。題外話一句吧,我一直覺得ctypes與xmlrpc并列Python語言的兩大神器,最能體現Python的生產效率。

希望本文在大家選擇一種技術路線時能提供一點點幫助。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 97中文| 91在线一区二区 | 亚洲精品无码成人A片色欲 亚洲欧美日韩激情在线观看 | 日韩视频在线一区二区 | 国产sm主人调教女m视频 | 国产三级在线视频 一区二区三区 | 精品免费在线视频 | 欧美日韩综合视频 | 久草成人网 | 一级特黄录像视频免费 | 特级毛片s级全部免费 | 亚洲av毛片一区二区久久 | 邪不压正免费观看完整高清视频 | 国产在线精品一区二区三区 | 91久久国产| 热er99久久6国产精品免费 | 午夜a狂野欧美一区二区 | 狠狠色丁香婷婷综合久久来 | 日本天天色 | 99热久 | 欧美日韩亚洲在线 | 免费视频精品一区二区 | 精品国产一区二区三区久久久蜜臀 | 欧美1区| 一级毛片私人影院老司机 | 国产 高清 在线 | 午夜影院在线播放 | 91麻豆精品国产91久久久更新资源速度超快 | 日韩美女av在线 | 日韩色在线 | 中文字幕一区二区三区四区 | 亚洲美女综合 | 在线精品亚洲欧美日韩国产 | 毛片毛片毛片毛片毛片毛片毛片 | 亚洲精品国产精品乱码不97 | 一级做一级爱a做片性视频视频 | 欧美国产二区 | av日韩在线免费观看 | 手机国产日韩高清免费看片 | 久草免费福利资源站 | 亚洲蜜桃AV色情精品成人 |