ctypes 中 64 位 dll 的持续溢出错误

persistent overflow error with 64bit dll in ctypes

我正在尝试使用第 3 方 DLL 文件来控制硬件(在我的例子中是翻译阶段)。我有 windows 10、64 位 python(带有 Jupyter 笔记本)。

我已经像这样导入了正确版本(64 位)的 dll 文件:

import ctypes, sys
PiUsbDll = ctypes.WinDLL("PiUsb")

我有一份 DLL 的 C++ 头文件副本。因此,我知道函数列表是什么以及它们采用什么参数。我已经为 DLL 文件中的每个函数定义了 restype 和 argtype,如下所示(# 行显示函数 def 根据 C++ 头文件)

# void * __stdcall piConnectMotor(int * ErrorNum, int SlideSerialNum);
PiUsbDll.piConnectMotor.restype = ctypes.c_void_p
PiUsbDll.piConnectMotor.argtypes = (ctypes.POINTER(ctypes.c_int),ctypes.c_int)

# void __stdcall piDisconnectMotor(void * devicePtr);
PiUsbDll.piDisconnectMotor.restype = None
PiUsbDll.piDisconnectMotor.argtypes = ctypes.c_void_p, #, defines a tuple

# int __stdcall piHomeMotor(int Velocity, void * devicePtr);
PiUsbDll.piHomeMotor.restype = ctypes.c_int
PiUsbDll.piHomeMotor.argtypes = (ctypes.c_int, ctypes.c_void_p)

# int __stdcall piRunMotorToPosition( int Position, int Velocity, void * devicePtr);
PiUsbDll.piRunMotorToPosition.restype = ctypes.c_int
PiUsbDll.piRunMotorToPosition.argtype = (ctypes.c_int, ctypes.c_int, ctypes.c_void_p)


.
.
.

我有 defined/initialized 个 ctypes 变量:

SlideSerialNum = ctypes.c_int(123) #serial number provided from manufacturer
Velocity = ctypes.c_int(10) # Allowed range 1-12
Position = ctypes.c_int(500) #Allowed range 0-1900
devicePtr = ctypes.c_void_p()
ErrorNum = ctypes.c_int() 
.
.
.

然后我这样调用函数(省略了几行中间代码)

# Connect to motor
devicePtr = PiUsbDll.piConnectMotor(ctypes.byref(ErrorNum),SlideSerialNum)

# Homing the motor
ErrorNum.value = PiUsbDll.piHomeMotor(Velocity,devicePtr)

#  Run to a position
ErrorNum.value = PiUsbDll.piRunMotorToPosition(Position,Velocity,devicePtr)
.
.
.

在这里,连接和归位一直工作正常,但 运行 一个位置失败并出现以下错误:

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

所以,看起来 devicePtr (a void*) 在 python 类型和 ctypes 之间的转换不一致。我希望定义 argtype 可以解决这个问题,但看起来并非如此。一种解决方案是回退到 32 位 python 版本(以及 32 位 DLL 文件),在这种情况下不会出现此问题,但如果可能的话我希望坚持使用 64 位。

我认为问题与我的案例中的 64 位第 3 方 DLL 文件有关。我已经切换到 32 位 DLL 文件,其中相同的 python 代码可以工作。

调用该函数时,尝试将其“转换”为 c_void_p,a la

devicePtr = c_void_p(PiUsbDll.piConnectMotor(ctypes.byref(ErrorNum),SlideSerialNum))

这对我有用,在 x64 Windows 和 x64 python 上面临类似的问题。 (您可以在之后执行 type(devicePtr),以检查类型是否正确)。我不确定为什么在这种情况下明确设置 restype 还不够好...