python - Python ctypes API 调用导致访问冲突
问题描述
我正在尝试使用 ctypes 在 python 中使用 FindFirstFileW 和 FindNextFileW 列出一个目录。FindFirstFileW 成功但 FindNextFileW 或 FindClose 导致 OSError: 异常:访问冲突写入 0xFFFFFFFFB8093F80
这是代码:
def assert_success(success):
if not success:
raise AssertionError(FormatError())
def assert_handle(handle):
if handle == INVALID_HANDLE_VALUE:
raise AssertionError(FormatError())
def FindFirstFileW(lpFileName):
wfd = WIN32_FIND_DATAW()
handle = windll.kernel32.FindFirstFileW(lpFileName, byref(wfd))
assert_handle(handle)
return handle, wfd
def FindNextFileW(handle):
wfd = WIN32_FIND_DATAW()
success = windll.kernel32.FindNextFileW(handle, byref(wfd))
assert_success(success)
return wfd
def FindClose(handle):
success = windll.kernel32.FindClose(handle)
assert_success(success)
return success
handle, wfd = FindFirstFileW('C:\\Windows\\*')
print(wfd.cFileName)
wfd = FindNextFileW(handle)
print(wfd.cFileName)
FindClose(handle)
解决方案
您尚未对正在使用的功能进行适当的 .argtypes
设置。假设返回值是例如,但句柄在 64 位 Python 上是 64 位的,并且被截断为 32 位。此外,您还可以获得类型检查调用的额外好处,因为您知道参数类型应该是什么。.restype
ctypes
c_int
ctypes
还建议.errcheck
自动检查返回值:
尝试这个:
from ctypes import *
from ctypes import wintypes as w
INVALID_HANDLE_VALUE = w.HANDLE(-1).value
ERROR_NO_MORE_FILES = 18
def boolcheck(result,func,args):
if not result:
raise WinError(get_last_error())
return None
# return True if more files
# return False if no more files
# raise exception for other reasons
def nomorecheck(result,func,args):
if not result and get_last_error() != ERROR_NO_MORE_FILES:
raise WinError(get_last_error())
return result
def handlecheck(result,func,args):
if result == INVALID_HANDLE_VALUE:
raise WinError(get_last_error())
return result
dll = WinDLL('kernel32',use_last_error=True)
dll.FindFirstFileW.argtypes = w.LPCWSTR,w.LPWIN32_FIND_DATAW
dll.FindFirstFileW.restype = w.HANDLE
dll.FindFirstFileW.errcheck = handlecheck
dll.FindNextFileW.argtypes = w.HANDLE,w.LPWIN32_FIND_DATAW
dll.FindNextFileW.restype = w.BOOL
dll.FindClose.errcheck = nomorecheck
dll.FindClose.argtypes = w.HANDLE,
dll.FindClose.restype = w.BOOL
dll.FindClose.errcheck = boolcheck
def find_files(directory):
wfd = w.WIN32_FIND_DATAW()
handle = dll.FindFirstFileW(directory, byref(wfd))
yield wfd.cFileName
while dll.FindNextFileW(handle, byref(wfd)):
yield wfd.cFileName
dll.FindClose(handle)
for file in find_files(r'c:\windows\*'):
print(file)
推荐阅读
- matplotlib - 如何从概率密度函数测量概率
- angular - Angular 6 更新 package.json 中过时的依赖项
- mysql - 如何在LabVIEW中查询MySQL ODBC版本
- javascript - vuejs 应用程序如何在 textarea 光标的位置显示组件?
- scala - 带有 webSocketClientFlow 的空流
- mysql - MySQL 从 2 个连接的表中选择最低价格
- c# - 将 wsa 标头添加到 SOAP 调用
- excel - 如果 MAX 为 TRUE,则 Excel 中的输出值
- ios - UITextField 文本内容在成为第一响应者时向右移动
- javascript - 在 vue 中使用复选框作为数据绑定