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

淺談Python程序與C++程序的聯(lián)合使用

系統(tǒng) 1609 0

作為Python程序員,應(yīng)該能夠正視Python的優(yōu)點與缺點。眾所周之,Python的運行速度是很慢的,特別是大數(shù)據(jù)量的運算時,Python會慢得讓人難以忍受。對于這種情況,“專業(yè)”的解決方案是用上numpy或者opencl。不過有時候為了一點小功能用上這種重型的解決方案很不劃算,或者有時候想要實現(xiàn)的操作在numpy里面沒有,需要我們自己用C語言來編寫。總之,我們使用Python與C++的混合編程能夠加快程序熱點的運算速度。

首先要提醒大家注意的是,在考慮聯(lián)合編程之前一定要找到程序運行的熱點。簡單一點地,使用標(biāo)準(zhǔn)庫的profile或者cProfile模塊找到最消耗CPU的位置,如果這個位置只簡單的消耗IO時間,通常換成C++程序的意義也不會很大,此時做聯(lián)合編程可能是事倍功半,起不到多大的效果。

還有些情況,Python程序員們想要使用操作系統(tǒng)或者外部模塊提供的函數(shù)。這些模塊一般是為C/C++程序員提供的。這時候也是Python與C++聯(lián)合編程的用武之地。

Python語言可以說是最好的膠水語言。僅就與C++聯(lián)合編程這個問題來講,依使用難度與功能來排列,Python社區(qū)提供了以下幾種解決方案:

1.使用標(biāo)準(zhǔn)庫ctypes直接調(diào)用C/C++編寫的動態(tài)鏈接庫。這是最簡單易用的方案。C/C++程序員使用自己的豐富的經(jīng)驗,把預(yù)定的功能實現(xiàn)為動態(tài)鏈接庫。而Python程序員只要知道這些動態(tài)鏈接庫函數(shù)的名稱、參數(shù)類型與返回值類型就能簡單地調(diào)用它。當(dāng)你傳入?yún)?shù)時,ctypes模塊會自動地把Python的對象成為C/C++所對應(yīng)的參數(shù)類型。比如以下調(diào)用Windows的API:

            
  #定義參數(shù)類型與函數(shù)名稱
  from ctypes.wintypes import UINT, DWORD
  GetLastInputInfo = ctypes.windll.user32.GetLastInputInfo
  class LASTINPUTINFO(ctypes.Structure):
    _fields_ = [("cbSize", UINT),
         ("dwTime", DWORD)]

  #開始調(diào)用DLL導(dǎo)出的函數(shù)
  def getLastInputTime_nt():
    info = LASTINPUTINFO()
    info.cbSize = ctypes.sizeof(info)
    info.dwTime = 0
    if not GetLastInputInfo(ctypes.byref(info)):
      raise WindowsError("")
    return info.dwTime


          

??? 在這里展示了如何構(gòu)造Windows的API所需要的結(jié)構(gòu)體,如何填充結(jié)構(gòu)體并分析返回值。

??? ctypes還能將Python函數(shù)提供給C/C++代碼作為回調(diào)函數(shù)。

??? 與其它解決方案相比。ctypes不需要程序員熟悉C/C++語言,不需要安裝一個C/C++的編譯器,它通過操作系統(tǒng)的接口直接操作C/C++代碼。而且ctypes是標(biāo)準(zhǔn)庫的一部分,只要安裝了Python就可以直接使用。這幾個原因使得它深受Python程序員的喜愛。

??? 而它的劣勢呢。首先,ctypes不能簡單調(diào)用C++程序,因為C++在編譯的時候使用了name mangling這個技術(shù)來實現(xiàn)函數(shù)的重載。C++會自動地為類的成員函數(shù)加上類名前綴。所以,C++程序員需要以C語言的調(diào)用約定來提供接口,沒有類,沒有重載函數(shù),沒有模板,沒有C++異常。不能直接調(diào)用現(xiàn)有的C++代碼可能是這個方案最大的缺點。

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

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

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

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

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

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


          

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

??? 劣勢呢,所謂用Python程序員所熟練的語法來編寫高速的運算代碼,乍一聽相當(dāng)?shù)赜形Α5侨绻胍钊氲乜刂苾?nèi)存與數(shù)據(jù)結(jié)構(gòu)時,程序員可能會發(fā)現(xiàn),現(xiàn)在他不得不熟練地掌握C/C++語言,然后用Cython的語法寫出來。以程序員們懶惰的性格,這反而是件難以忍受的事件。這或許是Cython本身并不大流行的主要原因吧。

4.使用boost.python。有意思的是,與ctypes/Cython形成鮮明的對比,boost.python傾向于讓C++程序員擁有更熟悉的編程環(huán)境。它讓C++程序員使用他所熟悉的C++語法直接控制Python的數(shù)據(jù)結(jié)構(gòu),調(diào)用Python的解釋器。它沒有像Cython那樣發(fā)明新的語法,而是直接使用C++的語法,編寫供Python使用的接口。與Cython同樣的道理,它的效率優(yōu)勝于ctypes。

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

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

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

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

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

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

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

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


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 一级毛片一级毛片一级毛片一级毛片 | 亚洲成人av一区二区 | 99久久99| 久久国产免费看 | 狠狠色狠狠色综合久久第一次 | 成人网站偷拍澡AAAA | 中文字幕 国产精品 | 2019中文字幕视频 | 成人黄色在线观看视频 | 国精品一区 | 午夜性刺激在线观看视频 | 超碰国产在线 | 91传媒蜜桃香蕉在线观看 | 精品在线观看国产 | 亚洲专区在线 | 精品久久一区二区三区 | 黄色av片在线观看 | 欧美精品一区二区免费 | 青娱乐精品在线 | 亚洲精品一区二区三区四区高清 | 一级做受毛片免费大片 | 国产成人精品一区在线播放 | 国产激情偷乱视频一区二区三区 | 久久久久无码国产精品一区 | 激情五月综合 | 国产日韩欧美在线观看不卡 | 亚洲A片V一区二区三区有声 | 天天碰天天 | 最新亚洲国产有精品 | 国产一级毛片午夜福 | 91精品最新国内在线播放 | 日日摸天天碰中文字幕 | 9191在线| 午夜精品一区二区三区免费视频 | 天天干天天舔天天操 | 久久视频这里只精品3国产 色偷偷偷 | 亚洲免费观看在线视频 | 草草视频手机在线观看视频 | 亚洲欧美日韩中文综合在线不卡 | 2019中文字幕视频 | 91尤物国产尤物福利 |