当在模块级别运行时,与在函数范围内运行时,是什么导致这些代码产生不同的结果?

2024-09-28 13:22:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过WindowsAPI的EnumDisplayMonitors枚举可用的显示监视器。但是,我有一些很奇怪的行为,我不知道。也就是说,函数正确运行,但只有当它不在函数内部时。在

如果我把它放在模块级别,如下所示:

模块代码

def _monitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData):
    print 'call result:', hMonitor, hdcMonitor, lprcMonitor, dwData

if __name__ == '__main__':
    # Callback Factory
    MonitorEnumProc = WINFUNCTYPE(
        ctypes.c_bool, 
        ctypes.wintypes.HMONITOR,
        ctypes.wintypes.HDC,
        ctypes.POINTER(RECT),
        ctypes.wintypes.LPARAM
    )

    # Make the callback function
    enum_callback = MonitorEnumProc(_monitorEnumProc)

    # Enumerate the windows
    print 'return code: %d' % windll.user32.EnumDisplayMonitors(
        None, 
        None,
        enum_callback,
        0
        )

一切如期进行。它为我连接的两个监视器打印出handlesrects。在

输出:

^{pr2}$

一切都很好。并且EnumDisplayMonitors函数返回一个非零值,表示一切按计划进行。在

现在,问题是,如果我把完全相同的代码插入一个函数,事情就会变得一团糟。在

功能代码

def _monitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData):
    print 'call result:', hMonitor, hdcMonitor, lprcMonitor, dwData

def enum_mons():
    # Callback Factory
    MonitorEnumProc = WINFUNCTYPE(
        ctypes.c_bool, 
        ctypes.wintypes.HMONITOR,
        ctypes.wintypes.HDC,
        ctypes.POINTER(RECT),
        ctypes.wintypes.LPARAM
    )

    # Make the callback function
    enum_callback = MonitorEnumProc(_monitorEnumProc)

    # Enumerate the windows
    print 'return code: %d' % windll.user32.EnumDisplayMonitors(
        None, 
        None,
        enum_callback,
        0
        )

if __name__ == '__main__':
    enum_mons()

所以,完全相同的代码,除了现在在函数内部。在

输出

call result: 65537 None <__main__.LP_RECT object at 0x02250E90> 0
0

它不是抛出所有附加的监视器和成功代码,而是只输出一个监视器和一个0,根据MSDN doc表示函数失败。在

有人知道是什么引起的吗?我被难住了!在


Tags: 函数代码nonecallbackenumctypes监视器print
1条回答
网友
1楼 · 发布于 2024-09-28 13:22:05

使用函数时,enum_callback的Python框架被垃圾回收时,enum_callback将被释放。因此,当Windows尝试为每个监视器调用它时,它是否仍然存在是一场竞赛。全局定义回调或使用类。在

此外,回调应返回True以继续枚举。在

import ctypes
from ctypes import wintypes 

LPRECT = ctypes.POINTER(wintypes.RECT)

# Callback Factory
MonitorEnumProc = ctypes.WINFUNCTYPE(
    ctypes.c_bool, 
    wintypes.HMONITOR,
    wintypes.HDC,
    LPRECT,
    wintypes.LPARAM)

ctypes.windll.user32.EnumDisplayMonitors.restype = wintypes.BOOL
ctypes.windll.user32.EnumDisplayMonitors.argtypes = [
    wintypes.HDC,
    LPRECT,
    MonitorEnumProc,
    wintypes.LPARAM]

def _monitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData):
    print 'call result:', hMonitor, hdcMonitor, lprcMonitor, dwData
    print lprcMonitor[0].right, lprcMonitor[0].bottom
    return True # continue enumeration

# Make the callback function
enum_callback = MonitorEnumProc(_monitorEnumProc)

def enum_mons():   
    '''Enumerate the display monitors.'''
    return ctypes.windll.user32.EnumDisplayMonitors(
        None, 
        None,
        enum_callback,
        0)

if __name__ == '__main__':
    print 'return code: %d' % enum_mons()

相关问题 更多 >

    热门问题