问题描述
我正在尝试使用第三方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不够“好” ...