使用Python ctypes调用kernel32.dll中InterlockedExchange函数失败求助
解决ctypes调用InterlockedExchange找不到函数的问题
问题原因
- 调用约定不匹配:kernel32.dll中的函数采用
stdcall调用约定,而你用ctypes.CDLL加载时默认是cdecl约定,导致无法匹配导出函数。 - 路径转义问题:代码里的
'C:\Windows\System32\kernel32.dll'中,\W和\S会被Python解析为转义字符,可能导致dll路径识别错误。 - 未声明函数签名:即使找到函数,不指定参数和返回值类型,后续调用也容易出现崩溃或错误结果。
修正后的代码
import ctypes # 用原始字符串避免转义,或把反斜杠替换成双反斜杠 dll_path = r'C:\Windows\System32\kernel32.dll' # 必须用WinDLL加载kernel32,适配stdcall调用约定 kernel32 = ctypes.WinDLL(dll_path, use_last_error=True) # 声明32位整数版本的InterlockedExchange参数和返回值类型 kernel32.InterlockedExchange.argtypes = [ctypes.POINTER(ctypes.c_long), ctypes.c_long] kernel32.InterlockedExchange.restype = ctypes.c_long # 若需操作64位整数,改用InterlockedExchange64并替换类型 # kernel32.InterlockedExchange64.argtypes = [ctypes.POINTER(ctypes.c_longlong), ctypes.c_longlong] # kernel32.InterlockedExchange64.restype = ctypes.c_longlong
关键说明
- WinDLL vs CDLL:Windows系统自带dll(如kernel32、user32)几乎都用
stdcall约定,必须用ctypes.WinDLL加载;CDLL仅适用于自定义的cdecl约定库。 - 显式声明函数类型:指定
argtypes和restype是ctypes的最佳实践,能避免因类型不匹配引发的各种异常。 - 64位场景适配:如果程序运行在64位系统且需操作64位共享变量,直接使用
InterlockedExchange64即可,用法与32位版本一致。
结合mmap实现跨服务原子操作示例
假设已通过mmap创建共享内存,可按以下方式实现原子交换:
import mmap # 创建存储32位整数的共享内存 shared_mem = mmap.mmap(-1, ctypes.sizeof(ctypes.c_long), tagname='MySharedMemory', access=mmap.ACCESS_WRITE) # 将共享内存转为可直接操作的c_long变量 shared_var = ctypes.c_long.from_buffer(shared_mem) # 原子交换:将shared_var的值替换为100,返回旧值 old_value = kernel32.InterlockedExchange(ctypes.byref(shared_var), 100) print(f"旧值: {old_value}, 新值: {shared_var.value}")
内容的提问来源于stack exchange,提问作者sumit singh
相关产品推荐
相关产品推荐

