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庫...