使用ctypes windll卸载64位dll时出现错误

7

我发现这里有几篇关于使用ctypes卸载dll的文章,我按照所述方式进行了操作:

from ctypes import *

file = CDLL('file.dll')

# do some stuff here

handle = file._handle # obtain the DLL handle

windll.kernel32.FreeLibrary(handle)

然而,我正在使用Python 64位版本,并且我的DLL也是为x64编译的,但是在上面的最后一行代码中出现了错误:

argument 1: <class 'OverflowError'>: int too long to convert

我检查了句柄,发现它是一个长整型(int64)的‘8791681138688’,那么这是否意味着windll.kernel32只处理int32句柄?Google搜索显示kernal32也适用于64位Windows。那么我该怎么处理呢?

1个回答

11

FreeLibrary 接受一个作为 C void * 指针定义的句柄。请参考Windows 数据类型。在函数指针的 argtypes 中设置该值:

import ctypes
from ctypes import wintypes

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)    
kernel32.FreeLibrary.argtypes = [wintypes.HMODULE]

Python中int或在Python 3中被重命名为intlong默认转换为C语言中的long,然后再转换为C语言中的int。即使在64位的Windows操作系统上,Microsoft也使用32位的long类型,这就是为什么会导致转换时出现OverflowError错误。

在拥有64位long的平台(实际上几乎所有其他64位操作系统),如果没有定义函数的argtypes参数,将指针作为Python整数进行传递可能会导致进程崩溃。最初的转换为long类型是可以正常工作的,因为它与指针大小相同。但是,随后将其强制转换为32位C int可能会默默地截断值。


1
然后是 kernel32.FreeLibrary(handle),而不是 windll.kernel32.FreeLibrary(handle),对吧? - endolith
1
@endolith,是的,这定义了在kernel32上缓存的FreeLibrary函数指针的原型。最好避免使用windll加载器,因为它是全局的,并且可能会导致常见共享库(如kernel32.dll)的软件包之间发生冲突。 - Eryk Sun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接