我在一个项目中工作,在这个项目中,我必须使用python为开发板构建GUI,这也是我的新手。我得到了DLL,它具有与开发板通信所需的功能。我有一个LabVIEW等价函数原型,它看起来像这样:
int32_t WriteFPGARegsC(int16_t *USBdev, int32_t *DUTSelect, int32_t *Array_RegsIn, int32_t *Array_RegsOut, int32_t *Array_RegEnable);
同样的原型在Visual Basic中也是这样的:
Public Declare Function WriteFPGARegsC Lib "USB_IO_for_VB6.dll" (ByRef USBdev As Short, ByVal DUTSelect As Integer, ByRef Array_RegsIn As Integer, ByRef Array_RegsOut As Integer, ByRef Array_RegEnable As Integer) As Integer
由于很多问题,我尝试用python而不是LabVIEW来访问这个函数。
传递给函数的最后三个参数需要是255个元素数组的地址。
我不知道如何在python的函数中传递指针!!
我用python编写了下面的短代码来访问这个函数:
USBdev = [0]
DUTSelect = [0]
RegsIn = [0] * 255
RegsOut = [0] * 255
RegEnable = [0] * 255
from ctypes import*
mydll = cdll.LoadLibrary("USB_IO_for_VB6.dll")
retmydll = mydll.WriteFPGARegsC(USBdev, DUTSelect, RegsIn, RegsOut, RegEnable)
执行此代码后,我得到以下错误消息:
Traceback (most recent call last):
File "D:\Kushal\ATLASS\Source_code\Atlass.py", line 12, in <module>
retmydll = mydll.WriteFPGARegsC(id(USBdev), id(DUTSelect), id(RegsIn), id(RegsOut), id(RegEnable))
ValueError: Procedure called with not enough arguments (20 bytes missing) or wrong calling convention
任何帮助都将不胜感激!非常感谢!
发布于 2018-07-12 04:00:24
正如[Python]: ctypes - A foreign function library for Python所说,有几件事要做,其中最重要的是为函数对象设置argtypes
和restype
。SO充满了类似的问题(我回答了其中的几个)。
无论如何,我准备了一个虚拟的例子(不要介意错误的倾向性),它只是为了说明机制。
code.c
#include <stdio.h>
#include <inttypes.h>
#define DIM 10 // Must be the SAME (well, or lower) than the constant defined in the Python code
__declspec(dllexport) int32_t __stdcall WriteFPGARegsC(int16_t *USBdev, int32_t *DUTSelect, int32_t *Array_RegsIn, int32_t *Array_RegsOut, int32_t *Array_RegEnable) {
int32_t ret = 99;
printf("From C:\n\t*USBdev: %d\n\t*DUTSelect: %d\n\tArray_RegsIn[0]: %d\n\tArray_RegsOut[0]: %d\n\tArray_RegEnable[0]: %d\n\n\tReturning: %d\n",
*USBdev, *DUTSelect, Array_RegsIn[0], Array_RegsOut[0], Array_RegEnable[0], ret);
for (int i = 0; i < DIM; i++) {
Array_RegsOut[i] *= *DUTSelect;
}
return ret;
}
code.py
import sys
import ctypes
DIM = 10 # Should be 255, but for demo purposes keep it smaller
uint_arr = ctypes.c_uint * DIM
ushort_arr = ctypes.c_ushort * DIM
uint_p = ctypes.POINTER(ctypes.c_uint)
ushort_p = ctypes.POINTER(ctypes.c_ushort)
def main():
dll = ctypes.WinDLL("USB_IO_for_VB6.dll")
func = dll.WriteFPGARegsC
func.argtypes = [ushort_p, uint_p, uint_p, uint_p, uint_p]
func.restype = ctypes.c_uint
usb_dev = ctypes.c_ushort(25)
dut_select = ctypes.c_uint(2)
regs_in = uint_arr(*range(20, 20 + DIM))
regs_out = uint_arr(*range(30, 30 + DIM))
reg_enable = uint_arr(*range(40, 40 + DIM))
nth = 5
print("Output register array: {:s}".format(" ".join(["{:d}".format(item) for item in regs_out])))
print("\tIts {:d}th element: {:d}\n".format(nth, regs_out[nth]))
ret = func(ctypes.byref(usb_dev), ctypes.byref(dut_select), regs_in, regs_out, reg_enable)
print("\nFunction returned: {:d}".format(ret))
print("Output register array: {:s}".format(" ".join(["{:d}".format(item) for item in regs_out])))
print("\tIts {:d}th element: {:d}\n".format(nth, regs_out[nth]))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
输出
(py35x64_test) e:\Work\Dev\StackOverflow\q051289410>"c:\Install\x86\Microsoft\Visual Community\2015\vc\vcvarsall.bat“amd64 (py35x64_test) e:\Work\Dev\StackOverflow\q051289410>dir /b代码.c code.py (py35x64_test) e:\Work\Dev\StackOverflow\q051289410>cl /nologo代码.c /link /DLL /OUT:USB_IO_for_VB6.dll代码.c创建库USB_IO_for_VB6.lib和对象USBe:\Work\Dev\StackOverflow\q051289410>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe“_IO_for_VB6.exp (py35x64_test) e:\Work\Dev\StackOverflow\q051289410>dir /b code.c code.obj code.py USB_IO_for_VB6.dll USB_IO_for_VB6.exp USB_IO_for_VB6.lib (py35x64_test) python3.5.4 (v3.5.4:3f56838,Aug 8 2017,02:17:05) win32输出寄存器数组上的MSC v.1900 64位(AMD64):30 31 32 33 34 35 36 37 38 39其第5个元素: 35 From C:*USBdev: 25 *DUTSelect: 2 Array_RegsIn: 20 Array_RegsOut: 30 Array_RegEnable: 40 Returning: 99函数返回: 99输出寄存器数组: 60 62 64 66 68 70 74 76 78其第5个元素: 70
邮箱:@EDIT0
https://stackoverflow.com/questions/51289410
复制相似问题