ctypes中具有64位dll的持久性溢出错误

问题描述

我正在尝试使用第三方DLL文件来控制硬件(在我的情况下为翻译阶段)。我有Windows 10、64位python(带有Jupyter笔记本)。

我已经导入了dll文件的正确版本(64位),如下所示:

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

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

# 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)


.
.
.

我已经使用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(void *)在python类型和ctypes之间转换不一致。我希望定义argtype可以解决此问题,但看起来并非如此。一种解决方案是退回到32位python版本(以及32位DLL文件),在该版本中不会出现此问题,但如果可能的话,我希望坚持使用64位。

解决方法

在我的情况下,我认为问题与64位第三方DLL文件有关。我已经切换到32位DLL文件,其中使用了相同的python代码。

,

调用函数时,请尝试将其“广播”到c_void_p,la

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

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