python - 在Python中传递DLL函数的指针

标签 python dll

我正在开发一个项目,我必须使用 python 为开发板构建一个 GUI,我也是新手。我得到了 DLL,它具有与开发板通信所需的功能。 我有 LabVIEW 等效函数原型(prototype),如下所示:

int32_t WriteFPGARegsC(int16_t *USBdev, int32_t *DUTSelect, int32_t *Array_RegsIn, int32_t *Array_RegsOut, int32_t *Array_RegEnable);

对于 Visual Basic,相同的原型(prototype)也如下所示:

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

任何帮助将不胜感激! 非常感谢!

最佳答案

[Python]: ctypes - A foreign function library for Python状态,有几件事要做,其中最重要的是为函数对象设置 argtypes 和 restype 。 SO充满了类似的问题(我回答了其中几个)。

无论如何,我准备了一个虚拟示例(不要介意容易出错),它只是为了说明机制。

代码.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 Studio Community\2015\vc\vcvarsall.bat" amd64

(py35x64_test) e:\Work\Dev\StackOverflow\q051289410>dir /b
code.c
code.py

(py35x64_test) e:\Work\Dev\StackOverflow\q051289410>cl /nologo code.c /link /DLL /OUT:USB_IO_for_VB6.dll
code.c
   Creating library USB_IO_for_VB6.lib and object USB_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) e:\Work\Dev\StackOverflow\q051289410>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32

Output register array: 30 31 32 33 34 35 36 37 38 39
        Its 5th element: 35

From C:
        *USBdev: 25
        *DUTSelect: 2
        Array_RegsIn[0]: 20
        Array_RegsOut[0]: 30
        Array_RegEnable[0]: 40

        Returning: 99

Function returned: 99
Output register array: 60 62 64 66 68 70 72 74 76 78
        Its 5th element: 70

@EDIT0:

  • 修改答案以尽可能接近真实场景,并解决评论中的问题
    • 明确地说,ctypes 数组可以像任何其他 Python 序列一样访问

关于python - 在Python中传递DLL函数的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51289410/

相关文章:

c# - 为 C# 项目创建 C++ DLL - 未导出函数

Python ctypes dll 加载错误 487

c# - 如何在 Windows Phone 8 (C#) Framework 中添加 C++ DLL

c++ - LoadLibrary 在 Win7 32 位上失败,在 Win XP 32 位上成功

python - 从一组预先计算的绘图创建动画 : ArtistAnimation

python - 处理不带参数但有时使用绑定(bind)事件调用的函数的最佳方法?

python - django 获取社会 token 形式 allauth

c++ - SQLConfigDataSource不会为64位驱动程序添加System DSN

python - 在 numpy 二维数组的每一行中放置一个的快速方法

python - 将值附加到 Django 模型