Python之ctypes模組用法

2021-09-12 01:58:40 字數 3646 閱讀 5346

目錄

簡要說明

開發環境

封裝資料結構 陣列

結構體 指標

列舉 函式傳遞結構體引數  備註

ctypes是python的外部函式庫。它提供c相容的資料型別,並允許在dll或共享庫中呼叫函式,它可以用於在純python中包裝這些庫。cdll 載入使用標準cdecl呼叫約定匯出函式的庫,而windll庫使用stdcall呼叫約定呼叫函式。呼叫形式如下:

from ctypes import *

clib = windll.loadlibrary("c:\\users\\ad\\desktop\\python_test\\python_visa_test\\***.dll")

作業系統:window7

python版本:3.4.4

對於c語言中經常用到的陣列、結構體、指標、列舉等型別,ctypes模組都提供了封裝。ctypes定義了許多原始的c相容資料型別,如下:

#char型的一位陣列,長度為8

x = c_char * 8

#int型的一位陣列,長度為8

y= c_int * 8

#int型的二維陣列(等同於c語言: int z[8][256])

z = y*256

ctypes中將結構體封裝成類,需要繼承structure,在_fields_中定義成員,如下:

class deviceinfo(structure):

x= c_char * 8

y = c_char * 8

z= c_char * 8

_fields_ = [("x1",x* 256),   #二維陣列

("y1",y* 256),

("z1",z* 256),

("n",c_int * 8),

("m",c_int),

("a",c_int),

("b",c_char * 8 )]

通過pointer在ctypes型別上呼叫函式 來建立指標例項:

from ctypes import *

i = c_int(42)

pi = pointer(i)

指標例項有乙個contents屬性,它返回指標指向的i物件,上面的物件:

>>> pi.contents

c_long(42)

>>>

注意,ctypes沒有oor(原始物件返回),每次檢索屬性時它都會構造乙個新的等效物件 :

>>> pi.contents is i

false

>>> pi.contents is pi.contents

false

>>>

將另乙個c_int例項分配給指標的contents屬性會導致指標指向儲存它的記憶體位置:

>>> i = c_int(99)

>>> pi.contents = i

>>> pi.contents

c_long(99)

>>>

pointer()函式不僅僅是建立指標例項,還必須首先建立指標型別。這是通過pointer()接受任何ctypes型別的函式完成的 ,並返回乙個新型別 :

>>> pi = pointer(c_int)

>>> pi

>>> pi(42)

traceback (most recent call last):

file "", line 1, in typeerror: expected c_long instead of int

>>> pi(c_int(42))

>>>

呼叫不帶引數的指標型別會建立乙個null指標。null指標有乙個false布林值:

>>> null_ptr = pointer(c_int)()

>>> print(bool(null_ptr))

false

>>>

ctypes檢查null何時解除引用指標(但解除引用無效的非null指標會使python崩潰): 

>>> null_ptr[0]

traceback (most recent call last):

....

valueerror: null pointer access

>>>

>>> null_ptr[0] = 1234

traceback (most recent call last):

....

valueerror: null pointer access

>>>

列舉需要繼承enum,如下:

from enum import enum

class cand(enum):

x= 0

y= 1

c庫中有這樣乙個函式:

int getdevinfo(deviceinfo *info,int counter,char *callback);

在ctypes中傳遞結構體,只能傳遞結構體指標,不能傳遞例項物件,並且呼叫c庫中的函式引數必須以ctypes基本資料型別封裝才能呼叫,如下:

#呼叫c庫函式

getdevinfo = clib .getdevinfo

#告訴ctypes資料型別

getdevinfo .argtypes= [pointer(deviceinfo ),c_int,pointer(c_char)]

t_callback = c_char()

#建立乙個結構體例項

t_devinfo = alldeviceinfo()

ret = getdevinfo (byref(t_devinfo ),c_int(3),byref(t_callback))

if(ret < 0):

print("call failed!")

else:

print("call success!")

在這裡只介紹了一些ctypes模組常用的地方,感興趣的同學,可以參照官方教程:

Ctypes模組實現python加速執行

一 我們以fibonacci數列的例子來看看,python的執行時間 def fibonacci n if n 2 return 1 else return fibonacci n 1 fibonacci n 2 begin time.time print fibonacci 40 over tim...

python使用ctypes呼叫擴充套件模組的例項方法

楔子 我們知道python的執行效率不是很高,而且由於gil的原因,導致python不能充分利用多核cpu。一般的解決方式是使用多程序,但是多程序開銷比較大,而且程序之間的通訊也會比較麻煩。因此在解決效率問題上,我們會把那些比較耗時的模組使用c或者c 編寫,然後編譯成動態鏈結庫,windows上面是...

python中ctypes的使用

window下,python銜接c語言程式設計 本地安裝64位的python3.5,visual studio 2017 step1 安裝visual studio 2017,提供c語言編譯器 即msvc版本,另一版本是linux下的gcc step2 選擇x64的命令列 step3 輸入pip i...