如何使用ctypes的errcheck?

时间:2018-06-03 18:57:57

标签: python ctypes

Python库参考,版本3.6.5,第16.16段ctypes - 一个用于Python的外部函数库,在部分给出了这个示例,演示了输出参数 >功能原型

win32 GetWindowRect 功能:

import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Column
    {
        anchors.fill: parent
        anchors.leftMargin: 10

        RadioButton
        {
            text: qsTr("System proxy")
            leftPadding: 0
        }

        RadioButton
        {
            text: qsTr("No proxy")
            leftPadding: 0
        }

        RadioButton
        {
            text: qsTr("Configure manually:")
            leftPadding: 0
        }

        Grid
        {
            columns: 5
            spacing: 10
            Label {text: " "}
            Label {text: qsTr("Address")}
            Label {text: qsTr("Port")}
            Label {text: qsTr("Login")}
            Label {text: qsTr("Password")}
            Label {text: "HTTP"}
            TextField {width: 100}
            TextField {width: 40}
            TextField {width: 100}
            TextField {width: 100}
        }
    }
}

ctypes 包装器:

WINUSERAPI BOOL WINAPI GetWindowRect(HWND hWnd, LPCRECT lprect);

现在,我如何实际使用 GetWindowRect

尝试

from ctypes             import POINTER, WINFUNCTYPE, windll, WinError
from ctypes.wintypes    import BOOL, HWND, RECT

prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
paramflags = (1, 'hwnd'), (2, 'lprect')
GetWindowRect = prototype(('GetWindowRect', windll.user32), paramflags)

返回from ctypes import byref, cast r = RECT() h = cast(65552, HWND) # _65552_ is the return value of _GetDesktopWindow_ on my system result = GetWindowRect([h, byref(r)])

1 个答案:

答案 0 :(得分:0)

[Python]: ctypes - A foreign function library for Python没有提供完整的示例。

code.py

#!/usr/bin/env python3

import sys
import ctypes
from ctypes import wintypes


def errcheck(result, func, args):
    if not result:
        raise ctypes.WinError()
    rc = args[1]
    return rc.left, rc.top, rc.bottom, rc.right


def test_get_window_rect(desktop_wnd_handle):
    print("\n{:s}\n".format(test_get_window_rect.__name__))
    prototype = ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, ctypes.POINTER(wintypes.RECT))
    paramflags = (1, "hwnd"), (2, "lprect")
    GetWindowRect = prototype(("GetWindowRect", ctypes.windll.user32), paramflags)

    print("Without errcheck:\n")
    result = GetWindowRect(ctypes.windll.user32.GetDesktopWindow())
    print("Left: {:d}, Top: {:}, Right: {:d}, Bottom: {:}".format(result.left, result.top, result.right, result.bottom))
    result = GetWindowRect(0)
    print("Left: {:d}, Top: {:}, Right: {:d}, Bottom: {:}".format(result.left, result.top, result.right, result.bottom))

    GetWindowRect.errcheck = errcheck

    print("\nWith errcheck:\n")
    result = GetWindowRect(desktop_wnd_handle)
    print("Left: {:d}, Top: {:}, Right: {:d}, Bottom: {:}".format(*result))
    result = GetWindowRect(0)
    print("Left: {:d}, Top: {:}, Right: {:d}, Bottom: {:}".format(*result))


def test_get_window_rect_old_style(desktop_wnd_handle):
    print("\n{:s}\n".format(test_get_window_rect_old_style.__name__))
    user32_dll = ctypes.WinDLL("user32")
    get_windows_rect_func = user32_dll.GetWindowRect
    get_windows_rect_func.argtypes = [wintypes.HWND, ctypes.POINTER(wintypes.RECT)]
    get_windows_rect_func.restype = wintypes.BOOL
    rect = wintypes.RECT()
    result = get_windows_rect_func(desktop_wnd_handle, ctypes.byref(rect))
    print("Result: {:d}\nLeft: {:d}, Top: {:}, Right: {:d}, Bottom: {:}".format(result, rect.left, rect.top, rect.right, rect.bottom))
    rect = wintypes.RECT()
    result = get_windows_rect_func(0, ctypes.byref(rect))
    print("Result: {:d}\nLeft: {:d}, Top: {:}, Right: {:d}, Bottom: {:}".format(result, rect.left, rect.top, rect.right, rect.bottom))


def main():
    hwnd = ctypes.windll.user32.GetDesktopWindow()
    test_get_window_rect_old_style(hwnd)
    test_get_window_rect(hwnd)


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

备注

  • 函数调用正常发生(无参数处理 - 将它们放在列表中),只指定输入参数
  • errcheck “magic”插图
  • 还包括调用函数的老式方法

<强>输出

(py35x64_test) e:\Work\Dev\StackOverflow\q050669907>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32


test_get_window_rect_old_style

Result: 1
Left: 0, Top: 0, Right: 1920, Bottom: 1080
Result: 0
Left: 0, Top: 0, Right: 0, Bottom: 0

test_get_window_rect

Without errcheck:

Left: 0, Top: 0, Right: 1920, Bottom: 1080
Left: 0, Top: 0, Right: 0, Bottom: 0

With errcheck:

Left: 0, Top: 0, Right: 1080, Bottom: 1920
Traceback (most recent call last):
  File "code.py", line 58, in <module>
    main()
  File "code.py", line 53, in main
    test_get_window_rect(hwnd)
  File "code.py", line 30, in test_get_window_rect
    result = GetWindowRect(0)
  File "code.py", line 9, in errcheck
    raise ctypes.WinError()
OSError: [WinError 1400] Invalid window handle.