Python中的ctypes使用場景
ctypes 是 Python 標準庫中的一個模塊,用于調(diào)用動態(tài)鏈接庫(如 .dll、.so、.dylib)中的 C 函數(shù),并與 C 兼容的數(shù)據(jù)類型進行交互。它允許 Python 程序直接與用 C/C++ 編寫的共享庫進行交互,而無需編寫額外的綁定代碼(如使用 Cython 或 SWIG)。這在需要高性能計算、復(fù)用已有 C 庫或操作系統(tǒng)底層接口時非常有用。
主要功能
- 加載動態(tài)鏈接庫
- Windows:
ctypes.WinDLL/ctypes.CDLL - Linux/macOS:
ctypes.CDLL - 示例:
- Windows:
import ctypes libc = ctypes.CDLL("libc.so.6") # Linux # 或 msvcrt = ctypes.CDLL("msvcrt.dll") # Windows- 調(diào)用 C 函數(shù)
- 加載后可像普通函數(shù)一樣調(diào)用:
result = libc.printf(b"Hello, %s\n", b"world")
- 數(shù)據(jù)類型映射
ctypes提供了與 C 類型對應(yīng)的 Python 類型,例如:- 示例結(jié)構(gòu)體
class Point(ctypes.Structure): _fields_ = [("x", ctypes.c_int), ("y", ctypes.c_int)] p = Point(10, 20)c_int,c_char,c_double,c_void_p等- 數(shù)組:
c_int * 10 - 結(jié)構(gòu)體:繼承
ctypes.Structure - 聯(lián)合體:繼承
ctypes.Union
- 數(shù)組:
- 指定函數(shù)參數(shù)和返回類型
- 默認情況下,
ctypes假設(shè)函數(shù)返回c_int,參數(shù)按 C 的默認規(guī)則轉(zhuǎn)換。 - 可顯式設(shè)置:
- 默認情況下,
libc.malloc.argtypes = [ctypes.c_size_t] libc.malloc.restype = ctypes.c_void_p
- 回調(diào)函數(shù)(Callback)
- 可將 Python 函數(shù)作為 C 函數(shù)指針傳入:python
CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int) def py_cmp(a, b): return a - b cmp_func = CMPFUNC(py_cmp)- 內(nèi)存管理
- 可通過
ctypes.create_string_buffer()創(chuàng)建可變內(nèi)存塊 - 注意:不當使用可能導(dǎo)致段錯誤(segmentation fault)
- 可通過
使用場景
- 調(diào)用系統(tǒng) API(如 Windows API)
- 復(fù)用高性能 C 庫(如數(shù)學(xué)計算、圖像處理)
- 與硬件驅(qū)動或嵌入式設(shè)備通信
- 快速原型開發(fā),避免重寫 C 代碼
檢查屏幕狀態(tài)
通過cypes加載Windows API的user32.dll動態(tài)鏈接庫
user32.dll是Windows系統(tǒng)中負責(zé)用戶界面相關(guān)功能的核心庫,提供了窗口管理、消息處理等功能
def check_screen_state():
user32 = ctypes.windll.user32
#GetDC函數(shù)用于獲取指定窗口的設(shè)備上下文(Device Context),0表示獲取整個屏幕的DC,而不是特定窗口的
hdc = user32.GetDC(0)
try:
# 獲取設(shè)備的特定能力值,109對應(yīng)WindowsAPI中的SM_CMONITORS常量,用于獲取系統(tǒng)中顯示器的數(shù)量
result = user32.GetDeviceCaps(hdc, 109) # 目的是檢查系統(tǒng)中是否有顯示器連接
if result == 0:
current_state = 'off'
else:
'''
SystemParametersInfoW是WindowsAPI中的一個核心函數(shù),用于獲取或設(shè)置各種系統(tǒng)參數(shù)。
后綴W表示這是Unicode版本的函數(shù),用于處理寬字符
BOOL SystemParametersInfoW(
UINT uiAction, // 要執(zhí)行的操作
UINT uiParam, // 操作相關(guān)的參數(shù)
PVOID pvParam, // 數(shù)據(jù)緩沖區(qū)指針
UINT fWinIni // 更新配置文件的標志
);
- 當調(diào)用 SystemParametersInfoW(16, 0, None, 0) 時:
- uiAction = SPI_GETSCREENSAVERRUNNING (16)
- uiParam = 0 (此操作不需要額外參數(shù))
- pvParam = None (在 Python 中,這里會返回布爾值)
- fWinIni = 0 (不需要更新配置文件)
- 返回值:如果屏幕保護程序正在運行,返回非零值;否則返回 0。
'''
is_screen_saver_running = user32.SystemParametersInfoW(16, 0, None, 0)
if is_screen_saver_running:
current_state = 'screensaver' // 屏幕保護程序運行
else:
# 參數(shù) 114 用于檢查顯示器電源管理是否已激活,對應(yīng)WindowsAPI中的常量SPI_GETTPOWEROFFACTIVE
is_monitor_off = user32.SystemParametersInfoW(114, 0, None, 0)
if is_monitor_off:
current_state = 'off' // 屏幕關(guān)閉
else:
current_state = 'on' // 屏幕亮起
except:
current_state = 'unknown' // 屏幕狀態(tài)未知
finally:
user32.ReleaseDC(0, hdc)
return current_state
注意事項
- 平臺依賴性:不同操作系統(tǒng)/架構(gòu)下,庫名稱、調(diào)用約定(calling convention)可能不同。
- ABI 兼容性:需確保調(diào)用的函數(shù)簽名與實際一致,否則程序可能崩潰。
- 安全性:
ctypes繞過了 Python 的內(nèi)存安全機制,錯誤使用可能導(dǎo)致嚴重問題。 - 性能開銷:雖然調(diào)用的是原生代碼,但頻繁的 Python ↔ C 轉(zhuǎn)換仍有開銷。
簡單示例:調(diào)用 C 標準庫的abs
import ctypes
# 加載 C 標準庫(Linux/macOS)
libc = ctypes.CDLL("libc.so.6") # macOS 可能是 "libc.dylib"
# 設(shè)置函數(shù)簽名
libc.abs.argtypes = [ctypes.c_int]
libc.abs.restype = ctypes.c_int
# 調(diào)用
print(libc.abs(-42)) # 輸出: 42在 Windows 上可使用
"msvcrt.dll"并調(diào)用abs。
總之,ctypes 是 Python 與 C 世界之間的一座橋梁,強大但需謹慎使用。對于更復(fù)雜或高頻的交互,也可考慮 cffi、pybind11 或 Cython 等替代方案。
到此這篇關(guān)于Python中的ctypes的文章就介紹到這了,更多相關(guān)Python ctypes內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用XML庫的方式,實現(xiàn)RPC通信的方法(推薦)
下面小編就為大家?guī)硪黄褂肵ML庫的方式,實現(xiàn)RPC通信的方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06
python爬蟲 基于requests模塊發(fā)起ajax的get請求實現(xiàn)解析
這篇文章主要介紹了python爬蟲 基于requests模塊發(fā)起ajax的get請求實現(xiàn)解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08
用Python的Flask框架結(jié)合MySQL寫一個內(nèi)存監(jiān)控程序
這篇文章主要介紹了用Python的Flask框架結(jié)合MySQL些一個內(nèi)存監(jiān)控程序的例子,并且能將結(jié)果作簡單的圖形化顯示,需要的朋友可以參考下2015-11-11

