第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在Python中包裝C庫:C,Cython或ctypes?

在Python中包裝C庫:C,Cython或ctypes?

largeQ 2019-10-12 14:43:48
我想從Python應用程序調用C庫。我不想包裝整個API,只包裝與我的情況相關的函數(shù)和數(shù)據(jù)類型。如我所見,我有三個選擇:在C中創(chuàng)建一個實際的擴展模塊??赡苡悬c過頭了,我還想避免學習擴展編寫的開銷。使用Cython將C庫的相關部分公開給Python。使用Python ctypes與外部庫進行通信,從而完成整個工作。我不確定2)還是3)是更好的選擇。3)的優(yōu)點是它ctypes是標準庫的一部分,并且生成的代碼將是純Python –盡管我不確定該優(yōu)點實際上有多大。兩種選擇都有其他優(yōu)點/缺點嗎?您推薦哪種方法?編輯:感謝您的所有回答,它們?yōu)橄M鲱愃剖虑榈娜魏稳颂峁┝撕芎玫馁Y源。當然,仍需針對單個案例做出決定-沒有人會回答“這是對的”。就我自己而言,我可能會使用ctypes,但我也期待在其他項目中試用Cython。由于沒有一個單一的真實答案,因此接受一個答案有些武斷。我選擇了FogleBird的答案,因為它提供了對ctypes的一些很好的了解,并且它也是當前投票最高的答案。但是,我建議您閱讀所有答案以獲得一個很好的概述。再次感謝。
查看完整描述

3 回答

?
九州編程

TA貢獻1785條經(jīng)驗 獲得超4個贊

ctypes 是快速完成它的最佳選擇,并且在仍在編寫Python的情況下很高興與您合作!


我最近包裝了一個FTDI驅動程序,用于使用ctypes與USB芯片通信,這很棒。我完成了所有工作,并在不到一天的時間內完成工作。(我只實現(xiàn)了我們需要的功能,大約有15個功能)。


出于同一目的,我們以前使用的是第三方模塊PyUSB。PyUSB是實際的C / Python擴展模塊。但是PyUSB在阻止讀寫操作時沒有釋放GIL,這給我們帶來了問題。因此,我使用ctypes編寫了自己的模塊,該模塊在調用本機函數(shù)時會釋放GIL。


需要注意的一件事是,ctypes不會知道#define所使用的庫中的常量和內容,而僅是函數(shù),因此您必須在自己的代碼中重新定義這些常量。


這是一個代碼最終的外觀示例(大量內容被刪除,只是試圖向您展示其要旨):


from ctypes import *


d2xx = WinDLL('ftd2xx')


OK = 0

INVALID_HANDLE = 1

DEVICE_NOT_FOUND = 2

DEVICE_NOT_OPENED = 3


...


def openEx(serial):

    serial = create_string_buffer(serial)

    handle = c_int()

    if d2xx.FT_OpenEx(serial, OPEN_BY_SERIAL_NUMBER, byref(handle)) == OK:

        return Handle(handle.value)

    raise D2XXException


class Handle(object):

    def __init__(self, handle):

        self.handle = handle

    ...

    def read(self, bytes):

        buffer = create_string_buffer(bytes)

        count = c_int()

        if d2xx.FT_Read(self.handle, buffer, bytes, byref(count)) == OK:

            return buffer.raw[:count.value]

        raise D2XXException

    def write(self, data):

        buffer = create_string_buffer(data)

        count = c_int()

        bytes = len(data)

        if d2xx.FT_Write(self.handle, buffer, bytes, byref(count)) == OK:

            return count.value

        raise D2XXException

有人對各種選項做了一些基準測試。


如果不得不包裝帶有許多類/模板/等的C ++庫,我可能會更加猶豫。但是ctypes可以很好地與結構配合使用,甚至可以回調到Python中。



查看完整回答
反對 回復 2019-10-12
?
桃花長相依

TA貢獻1860條經(jīng)驗 獲得超8個贊

警告:Cython核心開發(fā)人員的意見。

我?guī)缀蹩偸墙ㄗhCython勝過ctypes。原因是它具有更平滑的升級路徑。如果使用ctypes,一開始很多事情都會很簡單,用純Python編寫FFI代碼當然很酷,而無需編譯,構建依賴關系以及所有這些。但是,在某個時候,您幾乎肯定會發(fā)現(xiàn),您必須循環(huán)或以更長的一系列相互依賴的調用方式大量調用C庫,并且您希望加快速度。在這一點上,您會注意到無法使用ctypes做到這一點?;蛘?,當您需要回調函數(shù)并且發(fā)現(xiàn)您的Python回調代碼成為瓶頸時,您也想加快它的速度和/或也將它移入C。同樣,您不能使用ctypes做到這一點。

使用OTOH的Cython,您可以完全自由地使包裝和調用代碼變薄或變厚。您可以從對常規(guī)Python代碼的C代碼中進行簡單的調用開始,然后Cython會將它們轉換為本地C調用,而沒有任何額外的調用開銷,并且Python參數(shù)的轉換開銷非常低。當您發(fā)現(xiàn)需要對C庫進行太多昂貴的調用時,甚至在某些時候需要更高的性能時,可以開始使用靜態(tài)類型注釋周圍的Python代碼,并讓Cython為您直接對其進行優(yōu)化?;蛘撸梢蚤_始在Cython中重寫部分C代碼,以避免調用并在算法上專門化和加強循環(huán)。如果您需要快速回調,只需編寫具有適當簽名的函數(shù),然后將其直接傳遞到C回調注冊表即可。同樣,沒有開銷,并且它為您提供普通的C調用性能。而且在不太可能發(fā)生的情況下,您實際上無法在Cython中獲得足夠快的代碼,您仍然可以考慮用C(或C ++或Fortran)重寫其真正關鍵的部分,并自然地從本地從Cython代碼中調用它。但是,這實際上成了最后的選擇,而不是唯一的選擇。

因此,ctypes非常適合做簡單的事情并快速使某些事情運行。但是,一旦事情開始發(fā)展,您很可能會發(fā)現(xiàn)您最好從一開始就使用Cython。


查看完整回答
反對 回復 2019-10-12
  • 3 回答
  • 0 關注
  • 1130 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號