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 还不够好...
我正在尝试使用第 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 还不够好...