Python中ctypes的使用整理

2021-10-12 01:51:55 字數 4577 閱讀 3067

ctypes是python的乙個外部庫,提供和c語言相容的資料型別,可以很方便地呼叫c dll中的函式。ctypes的官方文件在這裡。

1. ctypes基本資料型別對映表

引數型別預先設定好,或者在呼叫函式時再把引數轉成相應的c_***型別。ctypes的型別對應如下:

ctypes typec typepython type

c_char

char

1-character string

c_wchar

wchar_t

1-character unicode string

c_byte

char

int/long

c_ubyte

unsigned char

int/long

c_bool

bool

bool

c_short

short

int/long

c_ushort

unsigned short

int/long

c_int

intint/long

c_uint

unsigned int

int/long

c_long

long

int/long

c_ulong

unsigned long

int/long

c_longlong

__int64 or longlong

int/long

c_ulonglong

unsigned __int64 or unsigned long long

int/long

c_float

float

float

c_double

double

float

c_longdouble

long double float

float

c_char_p

char *

string or none

c_wchar_p

wchar_t *

unicode or none

c_void_p

void *

int/long or none

對應的指標型別是在後面加上"_p",如int*是c_int_p等等。在python中要實現c語言中的結構,需要用到類。

2. 載入dll

訪問dll,首先需引入ctypes庫

from ctypes import *   

假設你已經有了乙個的dll(名字是add.dll),且該dll有乙個符合cdecl(這裡強調呼叫約定是因為,stdcall呼叫約定和cdecl呼叫約定宣告的匯出函式,在使用python載入時使用的載入函式是不同的,後面會有說明)呼叫約定的匯出函式add。

stdcall呼叫約定:兩種載入方式

objdll = ctypes.windll.loadlibrary("dllpath")

objdll = ctypes.windll("dllpath")

cdecl呼叫約定:也有兩種載入方式

objdll = ctypes.cdll.loadlibrary("dllpath")

objdll = ctypes.cdll("dllpath")

其實windll和cdll分別是windll類和cdll類的物件。 

3. 呼叫dll方法

載入dll後會返回乙個dll物件,使用其中的函式方法則相當於操作該物件的對應屬性。

注意,經過stdcall宣告的方法,如果不是用def檔案宣告的匯出函式或者extern 「c」 宣告的話,編譯器會對函式名進行修改

函式引數申明,通過設定函式的argtypes屬性

函式返回型別,函式預設返回c_int型別,如果需要返回其他型別,需要設定函式的restype屬性

4. 指標與引用

常用的通過呼叫ctypes型別的指標函式來建立指標例項:

from ctype import *

i = c_int(1)

pi = pointer(i)

對指標例項賦值只會改變其指向的記憶體位址,而不是改變記憶體的內容,與其他語言類似,如需要可改變內容的字串,可須使用create_string_buffer()

>>> p = create_string_buffer("hello", 10) # create a 10 byte buffer

>>> print sizeof(p), repr(p.raw)

10 'hello/x00/x00/x00/x00/x00'

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

>>> null_ptr = pointer(c_int)()

>>> print bool(null_ptr)

false

指標例項有乙個contents屬性,返回這個指標所指向的物件。

另外,byref()是用來傳遞引用引數,pointer()作為傳參通常會建立乙個實際的指標物件,當不需要實際指標物件時,則可使用byref()

5. 結構體型別處理

structures和unions必須繼承structure和union基礎類,它們都在ctypes模組中定義,每乙個子類必須定義個_fields_屬性,_fields_是乙個二維的tuples列表,包含著每個field的name及type,這field型別必須是乙個ctypes型別,如c_int,或者任何其他的繼承ctypes的型別,如structure, union, array, 指標等。

例如有乙個簡單結構,包含兩個整型x和y,可如下初始化乙個結構:

from ctypes import *

import types

class test(structure):

_fields_ = [('x', c_int),

('y', c_char)]

test1 = test(1, 2)

另外,如結構體用於鍊錶操作,即包含指向結構體指標時,若直接定義:

from ctypes import *

import types

class test(structure):

_fields_ = [('x', c_int),

('y', c_char),

('next', test)]

則python會報錯type未定義,:

from ctypes import *

import types

class test(structure):

pass

test._fields_ = [('x', c_int),

('y', c_char),

('next', pointer(test))]

6. 陣列定義

陣列包含乙個固定數目的相同型別的例項,常用建立陣列型別是對乙個資料型別與乙個正數相乘,例如:

arraytype = test * 10
初始化和使用陣列:

>>> from ctypes import *

>>> tenintegers = c_int * 10

>>> ii = tenintegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

>>> print ii

>>> for i in ii: print i,

python中ctypes的使用

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

python效率提公升 ctypes的使用

python執行效率緩慢,一直是為眾人所詬病的。不過還好,python的ctypes庫可以呼叫載入c c 的函式庫,這樣python中需要效率的部分就用c c 寫,從而極大地提公升python的執行效率。1.不用ctypes的示例 from time import time t time s 0fo...

Python之ctypes模組用法

目錄 簡要說明 開發環境 封裝資料結構 陣列 結構體 指標 列舉 函式傳遞結構體引數 備註 ctypes是python的外部函式庫。它提供c相容的資料型別,並允許在dll或共享庫中呼叫函式,它可以用於在純python中包裝這些庫。cdll 載入使用標準cdecl呼叫約定匯出函式的庫,而windll庫...