欧美三区_成人在线免费观看视频_欧美极品少妇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條評論
主站蜘蛛池模板: 91av在线免费视频 | 精品久久久久久久久久久 | 欧美视频性 | 亚洲最大成人综合 | 最新中文字幕日本 | 成人影音 | 欧美一级α片 | 久久国产精品99久久小说 | 亚洲在线视频观看 | 国产在线自在拍91精品黑人 | 99热最新网址 | 亚洲免费一级视频 | 欧美一区二区三区gg高清影视 | 国产精品无码人妻无码色情多人 | 日韩成人黄色片 | 国产精品xxxav免费视频 | 男人天堂av网站 | 亚洲欧美视频一区二区 | 西西人体大胆77777视频 | 四虎免费久久影院 | 网站国产 | 五月综合激情婷婷六月色窝 | 成人午夜毛片在线看 | 久久美女性网 | 国产精品你懂的在线播放 | 综合一区二区三区 | 精品国产一区二区三区久久久 | 日本无码成人片在线观看波多 | 性aaa| 国产日产精品久久久久快鸭 | 中文字幕在线一区二区三区 | a级粗大硬长爽猛视频免费 潘金莲强完整版 | 国产黄色片网站 | 亚洲精品一区久久久久久 | 免费在线黄色电影 | 日韩免费一级片 | 国产精品综合 | 欧美激情欧美激情在线五月 | www.爱色| 欧美日韩在线视频观看 | 日韩综合在线 |