使用ctypes windll卸载64位DLL时出错

7 投票
1 回答
4186 浏览
提问于 2025-04-18 05:41

我发现这里有好几个帖子在讨论如何使用ctypes卸载一个dll文件,我按照上面说的方法一步步做的。

file = CDLL('file.dll')

# do some stuff here

handle = file._handle # obtain the DLL handle

windll.kernel32.FreeLibrary(handle)

不过,我用的是64位的Python,而我的dll也是为x64编译的,结果在上面的最后一行出现了错误:

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

我检查了一下句柄,发现它是一个长整型(int64),值是'8791681138688'。这是不是意味着windll.kernel32只处理int32的句柄?我在谷歌上查了一下,发现kernel32也是支持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中,默认情况下,intlong(在Python 3中被称为 int)会被转换成C语言中的 long,然后再转成C语言中的 int。微软在64位Windows上也使用32位的 long,这就是为什么转换时会出现 OverflowError 的原因。

在那些有64位 long 的平台上(几乎所有其他的64位操作系统都是这样),如果你把一个指针当作Python整数传递,而没有定义函数的 argtypes,可能会导致程序崩溃。最开始转换成 long 是没问题的,因为它和指针的大小是一样的。但是,后面再转换成32位的C int 时,可能会悄悄地截断这个值。

撰写回答