通過python的ctypes模組調用C函數,常常需要用到使用者指標資料指標。如通過python調用Win32 API產生視窗時使用的視窗流程就是一個執行個體,本文通過這個執行個體說明如何在python對象和C語言中的指標對象進行相互轉換問題。
1、python對象轉換為C指標對象
當Python調用SetWindowLong綁定一個Python對象為使用者資料時,我們可以如此調用:
from ctypes import *
SetWindowLong= windll.user32.SetWindowLongA
SetWindowLong.restype = c_void_p
SetWindowLong.argtypes = [c_int, c_int, py_object]
CreateWindowEx = windll.user32.CreateWindowExA
CreateWindowEx.argtypes = [c_int,c_char_p,c_char_p,c_int,c_int,c_int,c_int,c_int,c_int,c_int,c_int,c_int]
CreateWindowEx.restype = InvalidHandle
pyObject = py_object(aQWidget) # 轉換一個已有的QtWidget對象為pyObject對象,相當於void*指標
hWnd = CreateWindowEx(dwExStyle,szClassName,szWndName,dwStyle,x,y,cx,cy,hWndParent,hMenu,hInstance,0)
SetWindowLong(hWnd,GWL_USERDATA,pyObject ) # 綁定使用者資料為void*指標
SetWindowLongPtr(hWnd,GWL_WNDPROC,s_globalWndProcEntryInstance) # Hook視窗流程
2、C指標對象轉換為Python對象
當靜態視窗流程派發到對象視窗流程時,需要轉換void*指標為python對象,我們可以如此調用:
def globalWndProcEntry(hWnd, nMsg, wParam, lParam):
'''全域視窗流程入口'''
# 嘗試得到視窗綁定的使用者資料
pUserData = GetWindowLongPtr(c_int(hWnd),GWL_USERDATA)
if not pUserData:
if nMsg in (WM_NCCREATE,WM_CREATE):
CreateStruct = cast(lParam, POINTER(CREATESTRUCT)).contents
pUserData = CreateStruct.lpCreateParams
SetWindowLongPtr(c_int(hWnd),GWL_USERDATA,pUserData)
aWindow = cast(pUserData,py_object).value
if hasattr(aWindow,"m_hWnd"):
aWindow.m_hWnd = hWnd
# 處理視窗流程
if pUserData:
aWindow = cast(pUserData,py_object).value
if hasattr(aWindow,"WndProc"):
return aWindow.WndProc(hWnd, nMsg, wParam,lParam)
else:
return DefWindowProc(hWnd,nMsg,wParam,lParam)
else:
return DefWindowProc(hWnd,nMsg,wParam,lParam)
s_globalWndProcEntryInstance = WNDPROC(globalWndProcEntry)