【问题标题】:Can access some kernel32 functions with ctypes in 32 bit but not 64 bit可以使用 32 位而不是 64 位的 ctypes 访问一些 kernel32 函数
【发布时间】:2018-03-02 12:34:53
【问题描述】:

我正在尝试在 64 位 python 应用程序中使用来自 kernel32 的 InterlockedExchange

这是我理想的工作代码:

import ctypes
from ctypes import *

interlockedValue = ctypes.c_long(5)

print(interlockedValue.value)

locked = ctypes.c_long(68)
print(windll.kernel32.InterlockedExchange(byref(interlockedValue),locked))

print(interlockedValue.value)

但是,这是我使用 64 位 python 3.5.2 的输出:

C:\Users\Douglas Sexton\Source\Repos\SharedMemory\SharedMemory\Python>python interlocked3.py
5
Traceback (most recent call last):
File "interlocked3.py", line 10, in <module>
print(windll.kernel32.InterlockedExchange(byref(interlockedValue), locked))
File "C:\Program Files (x86)\Python35\lib\ctypes\__init__.py", line 360, in __getattr__
func = self.__getitem__(name)
File "C:\Program Files (x86)\Python35\lib\ctypes\__init__.py", line 365, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'InterlockedExchange' not found

32 位的工作原理与我预期的一样:

C:\Users\Douglas Sexton\Source\Repos\SharedMemory\SharedMemory\Python>"C:\Program Files (x86)\Python36\python.exe" interlocked3.py
5
5
68

我也尝试从序数访问:

import ctypes
from ctypes import *

interlockedValue = ctypes.c_long(5)

print(interlockedValue.value)

locked = ctypes.c_long(68)

print(windll.kernel32[868](byref(interlockedValue), locked))

print(interlockedValue.value)

这对于 32 位具有相同的输出,但对于 64 位,这是输出:

C:\Users\Douglas Sexton\Source\Repos\SharedMemory\SharedMemory\Python>python interlocked.py
5
0
0

我现在尝试了几种不同的方法从 python 64 访问 InterlockedExchange,但似乎都遇到了同样的问题。我已经能够使用 python 64 中的其他 kernel32 函数。这让我发疯。

【问题讨论】:

  • 显然在 x64 ABI 中,InterlockedExchange 仅可用作编译器内在 _InterlockedExchange
  • 顺便说一句,对于 Windows API,最好使用 kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) 而不是 ctypes.windll.kernel32。这避免了在全局 windll 对象上缓存原型,并且还使 ctypes 能够保护 WinAPI 上一个错误值。在这种情况下,最后一个错误值可通过ctypes.get_last_error() 获得,您可以通过ctypes.set_last_error(value) 预先设置它。对于失败的调用,通过raise ctypes.WinError(ctypes.get_last_error()) 引发异常。
  • @eryksun 感谢您的评论。我想我可以创建一个 dll,它只是 InterlockedExchange 的包装器并使用它?
  • 如果您必须构建一个包装器,您也可以将问题划分为将相关方面移动到 C/C++ 中。 CFFI 和 Cython 使编写扩展模块变得更容易,并且可能更适合您的需求。

标签: windows python-3.x 64-bit ctypes kernel32


【解决方案1】:

我最终暂时不需要这个,但我能够为 InterlockedExchange 创建一个包装 dll 并从 64 进程成功使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    • 2018-05-29
    • 2018-02-06
    • 1970-01-01
    • 2016-07-13
    • 2013-11-26
    相关资源
    最近更新 更多