Python中的ctypes使用場景
ctypes 是 Python 標準庫中的一個模塊,用于調用動態(tài)鏈接庫(如 .dll、.so、.dylib)中的 C 函數(shù),并與 C 兼容的數(shù)據(jù)類型進行交互。它允許 Python 程序直接與用 C/C++ 編寫的共享庫進行交互,而無需編寫額外的綁定代碼(如使用 Cython 或 SWIG)。這在需要高性能計算、復用已有 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- 調用 C 函數(shù)
- 加載后可像普通函數(shù)一樣調用:
result = libc.printf(b"Hello, %s\n", b"world")
- 數(shù)據(jù)類型映射
ctypes提供了與 C 類型對應的 Python 類型,例如:- 示例結構體
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 - 結構體:繼承
ctypes.Structure - 聯(lián)合體:繼承
ctypes.Union
- 數(shù)組:
- 指定函數(shù)參數(shù)和返回類型
- 默認情況下,
ctypes假設函數(shù)返回c_int,參數(shù)按 C 的默認規(guī)則轉換。 - 可顯式設置:
- 默認情況下,
libc.malloc.argtypes = [ctypes.c_size_t] libc.malloc.restype = ctypes.c_void_p
- 回調函數(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)- 內存管理
- 可通過
ctypes.create_string_buffer()創(chuàng)建可變內存塊 - 注意:不當使用可能導致段錯誤(segmentation fault)
- 可通過
使用場景
- 調用系統(tǒng) API(如 Windows API)
- 復用高性能 C 庫(如數(shù)學計算、圖像處理)
- 與硬件驅動或嵌入式設備通信
- 快速原型開發(fā),避免重寫 C 代碼
檢查屏幕狀態(tài)
通過cypes加載Windows API的user32.dll動態(tài)鏈接庫
user32.dll是Windows系統(tǒng)中負責用戶界面相關功能的核心庫,提供了窗口管理、消息處理等功能
def check_screen_state():
user32 = ctypes.windll.user32
#GetDC函數(shù)用于獲取指定窗口的設備上下文(Device Context),0表示獲取整個屏幕的DC,而不是特定窗口的
hdc = user32.GetDC(0)
try:
# 獲取設備的特定能力值,109對應WindowsAPI中的SM_CMONITORS常量,用于獲取系統(tǒng)中顯示器的數(shù)量
result = user32.GetDeviceCaps(hdc, 109) # 目的是檢查系統(tǒng)中是否有顯示器連接
if result == 0:
current_state = 'off'
else:
'''
SystemParametersInfoW是WindowsAPI中的一個核心函數(shù),用于獲取或設置各種系統(tǒng)參數(shù)。
后綴W表示這是Unicode版本的函數(shù),用于處理寬字符
BOOL SystemParametersInfoW(
UINT uiAction, // 要執(zhí)行的操作
UINT uiParam, // 操作相關的參數(shù)
PVOID pvParam, // 數(shù)據(jù)緩沖區(qū)指針
UINT fWinIni // 更新配置文件的標志
);
- 當調用 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 用于檢查顯示器電源管理是否已激活,對應WindowsAPI中的常量SPI_GETTPOWEROFFACTIVE
is_monitor_off = user32.SystemParametersInfoW(114, 0, None, 0)
if is_monitor_off:
current_state = 'off' // 屏幕關閉
else:
current_state = 'on' // 屏幕亮起
except:
current_state = 'unknown' // 屏幕狀態(tài)未知
finally:
user32.ReleaseDC(0, hdc)
return current_state
注意事項
- 平臺依賴性:不同操作系統(tǒng)/架構下,庫名稱、調用約定(calling convention)可能不同。
- ABI 兼容性:需確保調用的函數(shù)簽名與實際一致,否則程序可能崩潰。
- 安全性:
ctypes繞過了 Python 的內存安全機制,錯誤使用可能導致嚴重問題。 - 性能開銷:雖然調用的是原生代碼,但頻繁的 Python ↔ C 轉換仍有開銷。
簡單示例:調用 C 標準庫的abs
import ctypes
# 加載 C 標準庫(Linux/macOS)
libc = ctypes.CDLL("libc.so.6") # macOS 可能是 "libc.dylib"
# 設置函數(shù)簽名
libc.abs.argtypes = [ctypes.c_int]
libc.abs.restype = ctypes.c_int
# 調用
print(libc.abs(-42)) # 輸出: 42在 Windows 上可使用
"msvcrt.dll"并調用abs。
總之,ctypes 是 Python 與 C 世界之間的一座橋梁,強大但需謹慎使用。對于更復雜或高頻的交互,也可考慮 cffi、pybind11 或 Cython 等替代方案。
到此這篇關于Python中的ctypes的文章就介紹到這了,更多相關Python ctypes內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python實現(xiàn)BackPropagation算法
這篇文章主要為大家詳細介紹了python實現(xiàn)BackPropagation算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
jupyter notebook運行命令顯示[*](解決辦法)
這篇文章主要介紹了jupyter notebook運行命令顯示[*],文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05

